ilmControl: rewrite sync_and_acquire_instance
[profile/ivi/wayland-ivi-extension.git] / ivi-layermanagement-api / ilmControl / src / ilm_control_wayland_platform.c
1 /**************************************************************************
2  *
3  * Copyright (C) 2013 DENSO CORPORATION
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  ****************************************************************************/
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <memory.h>
22 #include <errno.h>
23 #include <pthread.h>
24 #include <signal.h>
25 #include <stdbool.h>
26
27 #include <unistd.h>
28 #include <poll.h>
29
30 #include <sys/eventfd.h>
31
32 #include "ilm_common.h"
33 #include "ilm_control_platform.h"
34 #include "wayland-util.h"
35 #include "ivi-controller-client-protocol.h"
36
37 /* GCC visibility */
38 #if defined(__GNUC__) && __GNUC__ >= 4
39 #define ILM_EXPORT __attribute__ ((visibility("default")))
40 #else
41 #define ILM_EXPORT
42 #endif
43
44 struct surface_context {
45     struct wl_list link;
46
47     struct ivi_surface *surface;
48     struct ivi_controller_surface *controller;
49
50     t_ilm_uint id_surface;
51     struct ilmSurfaceProperties prop;
52     surfaceNotificationFunc notification;
53
54     struct {
55         struct wl_list link;
56     } order;
57
58     struct wayland_context *ctx;
59     bool is_surface_creation_noticed;
60 };
61
62 struct layer_context {
63     struct wl_list link;
64
65     struct ivi_controller_layer *controller;
66     t_ilm_uint id_layer;
67
68     struct ilmLayerProperties prop;
69     layerNotificationFunc notification;
70
71     struct {
72         struct wl_list list_surface;
73         struct wl_list link;
74     } order;
75
76     struct wayland_context *ctx;
77 };
78
79 struct screen_context {
80     struct wl_list link;
81
82     struct wl_output *output;
83     struct ivi_controller_screen *controller;
84     t_ilm_uint id_from_server;
85     t_ilm_uint id_screen;
86
87     struct ilmScreenProperties prop;
88
89     struct {
90         struct wl_list list_layer;
91     } order;
92
93     struct ilm_control_context *ctx;
94 };
95
96 struct nativehandle_context {
97     uint32_t pid;
98     uint32_t nativehandle;
99     struct wl_list link;
100 };
101
102 struct wayland_context {
103     struct wl_display *display;
104     struct wl_registry *registry;
105     struct wl_event_queue *queue;
106     struct wl_compositor *compositor;
107     struct ivi_controller *controller;
108     uint32_t num_screen;
109
110     struct wl_list list_surface;
111     struct wl_list list_layer;
112     struct wl_list list_screen;
113 };
114
115 struct ilm_control_context {
116     struct wayland_context wl;
117     bool initialized;
118
119     uint32_t internal_id_layer;
120
121     struct wl_list list_nativehandle;
122
123     pthread_t thread;
124     pthread_mutex_t mutex;
125     int shutdown_fd;
126     uint32_t internal_id_surface;
127 };
128
129 static void roundtrip_done(void *data, struct wl_callback *callback,
130                            uint32_t serial)
131 {
132     (void) callback;
133     (void) serial;
134
135     *(int *)data = 1;
136 }
137
138 static struct wl_callback_listener roundtrip_listener = {roundtrip_done};
139
140 int display_roundtrip_queue(struct wl_display *display,
141                             struct wl_event_queue *queue)
142 {
143     int done = 0;
144     int ret = 0;
145     struct wl_callback *callback = wl_display_sync(display);
146     wl_proxy_set_queue((void *)callback, queue);
147     wl_callback_add_listener(callback, &roundtrip_listener, &done);
148
149     while (ret != -1 && !done)
150     {
151         ret = wl_display_dispatch_queue(display, queue);
152     }
153
154     wl_callback_destroy(callback);
155
156     return ret;
157 }
158
159 static inline void lock_context(struct ilm_control_context *ctx)
160 {
161    pthread_mutex_lock(&ctx->mutex);
162 }
163
164 static inline void unlock_context(struct ilm_control_context *ctx)
165 {
166    pthread_mutex_unlock(&ctx->mutex);
167 }
168
169 static int init_control(void);
170
171 static ilmErrorTypes impl_sync_and_acquire_instance(struct ilm_control_context *ctx);
172
173 static struct surface_context* get_surface_context(struct wayland_context *, uint32_t);
174
175 static void release_instance(void);
176
177 static int create_controller_layer(struct wayland_context *ctx, t_ilm_uint width, t_ilm_uint height, t_ilm_layer layerid);
178
179 static int32_t
180 wayland_controller_is_inside_surface_list(struct wl_list *list,
181                                           uint32_t id_surface)
182 {
183     struct surface_context *ctx_surf = NULL;
184     wl_list_for_each(ctx_surf, list, link) {
185         if (ctx_surf->id_surface == id_surface) {
186             return 1;
187         }
188     }
189
190     return 0;
191 }
192
193 static int32_t
194 wayland_controller_is_inside_layer_list(struct wl_list *list,
195                                         uint32_t id_layer)
196 {
197     struct layer_context *ctx_layer = NULL;
198     wl_list_for_each(ctx_layer, list, link) {
199         if (ctx_layer->id_layer == id_layer) {
200             return 1;
201         }
202     }
203
204     return 0;
205 }
206
207 static struct layer_context*
208 wayland_controller_get_layer_context(struct wayland_context *ctx,
209                                      uint32_t id_layer)
210 {
211     struct layer_context *ctx_layer = NULL;
212
213     if (ctx->controller == NULL) {
214         fprintf(stderr, "controller is not initialized in ilmControl\n");
215         return NULL;
216     }
217
218     wl_list_for_each(ctx_layer, &ctx->list_layer, link) {
219         if (ctx_layer->id_layer == id_layer) {
220             return ctx_layer;
221         }
222     }
223
224     fprintf(stderr, "failed to get layer context in ilmControl\n");
225     return NULL;
226 }
227
228 static void
229 output_listener_geometry(void *data,
230                          struct wl_output *output,
231                          int32_t x,
232                          int32_t y,
233                          int32_t physical_width,
234                          int32_t physical_height,
235                          int32_t subpixel,
236                          const char *make,
237                          const char *model,
238                          int32_t transform)
239 {
240     (void)output;
241     (void)x;
242     (void)y;
243     (void)subpixel;
244     (void)make;
245     (void)model;
246     (void)transform;
247 }
248
249 static void
250 output_listener_mode(void *data,
251                      struct wl_output *output,
252                      uint32_t flags,
253                      int32_t width,
254                      int32_t height,
255                      int32_t refresh)
256 {
257     (void)data;
258     (void)output;
259     (void)flags;
260     (void)width;
261     (void)height;
262     (void)refresh;
263
264     if (flags & WL_OUTPUT_MODE_CURRENT)
265     {
266         struct screen_context *ctx_scrn = data;
267         ctx_scrn->prop.screenWidth = width;
268         ctx_scrn->prop.screenHeight = height;
269     }
270 }
271
272 static void
273 output_listener_done(void *data,
274                      struct wl_output *output)
275 {
276     (void)data;
277     (void)output;
278 }
279
280 static void
281 output_listener_scale(void *data,
282                       struct wl_output *output,
283                       int32_t factor)
284 {
285     (void)data;
286     (void)output;
287     (void)factor;
288 }
289
290 static struct wl_output_listener output_listener = {
291     output_listener_geometry,
292     output_listener_mode,
293     output_listener_done,
294     output_listener_scale
295 };
296
297 static struct screen_context*
298 get_screen_context_by_serverid(struct wayland_context *ctx,
299                                uint32_t id_screen)
300 {
301     struct screen_context *ctx_scrn = NULL;
302
303     wl_list_for_each(ctx_scrn, &ctx->list_screen, link) {
304         if (ctx_scrn->id_from_server == id_screen) {
305             return ctx_scrn;
306         }
307     }
308     return NULL;
309 }
310
311 static void
312 add_orderlayer_to_screen(struct layer_context *ctx_layer,
313                          struct wl_output* output)
314 {
315     struct screen_context *ctx_scrn = wl_output_get_user_data(output);
316
317     int found = 0;
318     struct layer_context *layer_link;
319     wl_list_for_each(layer_link, &ctx_scrn->order.list_layer, order.link) {
320         if (layer_link == ctx_layer) {
321             found = 1;
322             break;
323         }
324     }
325
326     if (found == 0) {
327         wl_list_init(&ctx_layer->order.link);
328         wl_list_insert(&ctx_scrn->order.list_layer, &ctx_layer->order.link);
329     }
330 }
331
332 static void
333 remove_orderlayer_from_screen(struct layer_context *ctx_layer)
334 {
335     wl_list_remove(&ctx_layer->order.link);
336     wl_list_init(&ctx_layer->order.link);
337 }
338
339 static void
340 controller_layer_listener_visibility(void *data,
341                             struct ivi_controller_layer *controller,
342                             int32_t visibility)
343 {
344     struct layer_context *ctx_layer = data;
345
346     ctx_layer->prop.visibility = (t_ilm_bool)visibility;
347
348     if (ctx_layer->notification != NULL) {
349         ctx_layer->notification(ctx_layer->id_layer,
350                                 &ctx_layer->prop,
351                                 ILM_NOTIFICATION_VISIBILITY);
352     }
353 }
354
355 static void
356 controller_layer_listener_opacity(void *data,
357                        struct ivi_controller_layer *controller,
358                        wl_fixed_t opacity)
359 {
360     struct layer_context *ctx_layer = data;
361
362     ctx_layer->prop.opacity = (t_ilm_float)wl_fixed_to_double(opacity);
363
364     if (ctx_layer->notification != NULL) {
365         ctx_layer->notification(ctx_layer->id_layer,
366                                 &ctx_layer->prop,
367                                 ILM_NOTIFICATION_OPACITY);
368     }
369 }
370
371 static void
372 controller_layer_listener_source_rectangle(void *data,
373                                 struct ivi_controller_layer *controller,
374                                 int32_t x,
375                                 int32_t y,
376                                 int32_t width,
377                                 int32_t height)
378 {
379     struct layer_context *ctx_layer = data;
380
381     ctx_layer->prop.sourceX = (t_ilm_uint)x;
382     ctx_layer->prop.sourceY = (t_ilm_uint)y;
383     ctx_layer->prop.sourceWidth = (t_ilm_uint)width;
384     ctx_layer->prop.sourceHeight = (t_ilm_uint)height;
385     if (ctx_layer->prop.origSourceWidth == 0) {
386         ctx_layer->prop.origSourceWidth = (t_ilm_uint)width;
387     }
388     if (ctx_layer->prop.origSourceHeight == 0) {
389         ctx_layer->prop.origSourceHeight = (t_ilm_uint)height;
390     }
391
392     if (ctx_layer->notification != NULL) {
393         ctx_layer->notification(ctx_layer->id_layer,
394                                 &ctx_layer->prop,
395                                 ILM_NOTIFICATION_SOURCE_RECT);
396     }
397 }
398
399 static void
400 controller_layer_listener_destination_rectangle(void *data,
401                                      struct ivi_controller_layer *controller,
402                                      int32_t x,
403                                      int32_t y,
404                                      int32_t width,
405                                      int32_t height)
406 {
407     struct layer_context *ctx_layer = data;
408
409     ctx_layer->prop.destX = (t_ilm_uint)x;
410     ctx_layer->prop.destY = (t_ilm_uint)y;
411     ctx_layer->prop.destWidth = (t_ilm_uint)width;
412     ctx_layer->prop.destHeight = (t_ilm_uint)height;
413
414     if (ctx_layer->notification != NULL) {
415         ctx_layer->notification(ctx_layer->id_layer,
416                                 &ctx_layer->prop,
417                                 ILM_NOTIFICATION_DEST_RECT);
418     }
419 }
420
421 static void
422 controller_layer_listener_configuration(void *data,
423                           struct ivi_controller_layer *controller,
424                           int32_t width,
425                           int32_t height)
426 {
427     struct layer_context *ctx_layer = data;
428
429     ctx_layer->prop.sourceWidth = (t_ilm_uint)width;
430     ctx_layer->prop.sourceHeight = (t_ilm_uint)height;
431 }
432
433 static void
434 controller_layer_listener_orientation(void *data,
435                              struct ivi_controller_layer *controller,
436                              int32_t orientation)
437 {
438     ilmOrientation ilmorientation = ILM_ZERO;
439     struct layer_context *ctx_layer = data;
440
441     switch(orientation) {
442     case IVI_CONTROLLER_SURFACE_ORIENTATION_0_DEGREES:
443         ilmorientation = ILM_ZERO;
444         break;
445     case IVI_CONTROLLER_SURFACE_ORIENTATION_90_DEGREES:
446         ilmorientation = ILM_NINETY;
447         break;
448     case IVI_CONTROLLER_SURFACE_ORIENTATION_180_DEGREES:
449         ilmorientation = ILM_ONEHUNDREDEIGHTY;
450         break;
451     case IVI_CONTROLLER_SURFACE_ORIENTATION_270_DEGREES:
452         ilmorientation = ILM_TWOHUNDREDSEVENTY;
453         break;
454     default:
455         break;
456     }
457
458     ctx_layer->prop.orientation = ilmorientation;
459
460     if (ctx_layer->notification != NULL) {
461         ctx_layer->notification(ctx_layer->id_layer,
462                                 &ctx_layer->prop,
463                                 ILM_NOTIFICATION_ORIENTATION);
464     }
465 }
466
467 static void
468 controller_layer_listener_screen(void *data,
469                                  struct ivi_controller_layer *controller,
470                                  struct wl_output *output)
471 {
472     struct layer_context *ctx_layer = data;
473
474     if (output == NULL) {
475         remove_orderlayer_from_screen(ctx_layer);
476     } else {
477         add_orderlayer_to_screen(ctx_layer, output);
478     }
479 }
480
481 static void
482 controller_layer_listener_destroyed(void *data,
483                                     struct ivi_controller_layer *controller)
484 {
485     struct layer_context *ctx_layer = data;
486     wl_list_remove(&ctx_layer->link);
487     free(ctx_layer);
488 }
489
490 static struct ivi_controller_layer_listener controller_layer_listener =
491 {
492     controller_layer_listener_visibility,
493     controller_layer_listener_opacity,
494     controller_layer_listener_source_rectangle,
495     controller_layer_listener_destination_rectangle,
496     controller_layer_listener_configuration,
497     controller_layer_listener_orientation,
498     controller_layer_listener_screen,
499     controller_layer_listener_destroyed
500 };
501
502 static void
503 add_ordersurface_to_layer(struct surface_context *ctx_surf,
504                           struct ivi_controller_layer *layer)
505 {
506     struct layer_context *ctx_layer = NULL;
507     struct surface_context *link = NULL;
508     int found = 0;
509
510     ctx_layer = ivi_controller_layer_get_user_data(layer);
511
512     wl_list_for_each(link, &ctx_layer->order.list_surface, order.link) {
513         if (link == ctx_surf) {
514             found = 1;
515             break;
516         }
517     }
518
519     if (found == 0) {
520         wl_list_init(&ctx_surf->order.link);
521         wl_list_insert(&ctx_layer->order.list_surface, &ctx_surf->order.link);
522     }
523 }
524
525 static void
526 remove_ordersurface_from_layer(struct surface_context *ctx_surf)
527 {
528     wl_list_remove(&ctx_surf->order.link);
529     wl_list_init(&ctx_surf->order.link);
530 }
531
532 static void
533 controller_surface_listener_visibility(void *data,
534                             struct ivi_controller_surface *controller,
535                             int32_t visibility)
536 {
537     struct surface_context *ctx_surf = data;
538
539     ctx_surf->prop.visibility = (t_ilm_bool)visibility;
540
541     if (ctx_surf->notification != NULL) {
542         ctx_surf->notification(ctx_surf->id_surface,
543                                 &ctx_surf->prop,
544                                 ILM_NOTIFICATION_VISIBILITY);
545     }
546 }
547
548 static void
549 controller_surface_listener_opacity(void *data,
550                          struct ivi_controller_surface *controller,
551                          wl_fixed_t opacity)
552 {
553     struct surface_context *ctx_surf = data;
554
555     ctx_surf->prop.opacity = (t_ilm_float)wl_fixed_to_double(opacity);
556
557     if (ctx_surf->notification != NULL) {
558         ctx_surf->notification(ctx_surf->id_surface,
559                                 &ctx_surf->prop,
560                                 ILM_NOTIFICATION_OPACITY);
561     }
562 }
563
564 static void
565 controller_surface_listener_configuration(void *data,
566                            struct ivi_controller_surface *controller,
567                            int32_t width,
568                            int32_t height)
569 {
570     struct surface_context *ctx_surf = data;
571
572     ctx_surf->prop.sourceWidth = (t_ilm_uint)width;
573     ctx_surf->prop.sourceHeight = (t_ilm_uint)height;
574 }
575
576 static void
577 controller_surface_listener_source_rectangle(void *data,
578                                   struct ivi_controller_surface *controller,
579                                   int32_t x,
580                                   int32_t y,
581                                   int32_t width,
582                                   int32_t height)
583 {
584     struct surface_context *ctx_surf = data;
585
586     ctx_surf->prop.sourceX = (t_ilm_uint)x;
587     ctx_surf->prop.sourceY = (t_ilm_uint)y;
588     ctx_surf->prop.sourceWidth = (t_ilm_uint)width;
589     ctx_surf->prop.sourceHeight = (t_ilm_uint)height;
590     if (ctx_surf->prop.origSourceWidth == 0) {
591         ctx_surf->prop.origSourceWidth = (t_ilm_uint)width;
592     }
593     if (ctx_surf->prop.origSourceHeight == 0) {
594         ctx_surf->prop.origSourceHeight = (t_ilm_uint)height;
595     }
596
597     if (ctx_surf->notification != NULL) {
598         ctx_surf->notification(ctx_surf->id_surface,
599                                 &ctx_surf->prop,
600                                 ILM_NOTIFICATION_SOURCE_RECT);
601     }
602 }
603
604 static void
605 controller_surface_listener_destination_rectangle(void *data,
606                    struct ivi_controller_surface *controller,
607                    int32_t x,
608                    int32_t y,
609                    int32_t width,
610                    int32_t height)
611 {
612     struct surface_context *ctx_surf = data;
613
614     ctx_surf->prop.destX = (t_ilm_uint)x;
615     ctx_surf->prop.destY = (t_ilm_uint)y;
616     ctx_surf->prop.destWidth = (t_ilm_uint)width;
617     ctx_surf->prop.destHeight = (t_ilm_uint)height;
618
619     if (ctx_surf->notification != NULL) {
620         ctx_surf->notification(ctx_surf->id_surface,
621                                 &ctx_surf->prop,
622                                 ILM_NOTIFICATION_DEST_RECT);
623     }
624 }
625
626 static void
627 controller_surface_listener_orientation(void *data,
628                              struct ivi_controller_surface *controller,
629                              int32_t orientation)
630 {
631     struct surface_context *ctx_surf = data;
632     ilmOrientation ilmorientation = ILM_ZERO;
633
634     switch (orientation) {
635     case IVI_CONTROLLER_SURFACE_ORIENTATION_0_DEGREES:
636         ilmorientation = ILM_ZERO;
637         break;
638     case IVI_CONTROLLER_SURFACE_ORIENTATION_90_DEGREES:
639         ilmorientation = ILM_NINETY;
640         break;
641     case IVI_CONTROLLER_SURFACE_ORIENTATION_180_DEGREES:
642         ilmorientation = ILM_ONEHUNDREDEIGHTY;
643         break;
644     case IVI_CONTROLLER_SURFACE_ORIENTATION_270_DEGREES:
645         ilmorientation = ILM_TWOHUNDREDSEVENTY;
646         break;
647     default:
648         break;
649     }
650
651     ctx_surf->prop.orientation = ilmorientation;
652
653     if (ctx_surf->notification != NULL) {
654         ctx_surf->notification(ctx_surf->id_surface,
655                                 &ctx_surf->prop,
656                                 ILM_NOTIFICATION_ORIENTATION);
657     }
658 }
659
660 static void
661 controller_surface_listener_pixelformat(void *data,
662                              struct ivi_controller_surface *controller,
663                              int32_t pixelformat)
664 {
665     struct surface_context *ctx_surf = data;
666
667     ctx_surf->prop.pixelformat = (t_ilm_uint)pixelformat;
668 }
669
670 static void
671 controller_surface_listener_layer(void *data,
672                                   struct ivi_controller_surface *controller,
673                                   struct ivi_controller_layer *layer)
674 {
675     struct surface_context *ctx_surf = data;
676
677     if (layer == NULL) {
678         remove_ordersurface_from_layer(ctx_surf);
679     } else {
680         add_ordersurface_to_layer(ctx_surf, layer);
681     }
682 }
683
684 static void
685 controller_surface_listener_stats(void *data,
686                                   struct ivi_controller_surface *controller,
687                                   uint32_t redraw_count,
688                                   uint32_t frame_count,
689                                   uint32_t update_count,
690                                   uint32_t pid,
691                                   const char *process_name)
692 {
693     struct surface_context *ctx_surf = data;
694     (void)process_name;
695
696     ctx_surf->prop.drawCounter = (t_ilm_uint)redraw_count;
697     ctx_surf->prop.frameCounter = (t_ilm_uint)frame_count;
698     ctx_surf->prop.updateCounter = (t_ilm_uint)update_count;
699     ctx_surf->prop.creatorPid = (t_ilm_uint)pid;
700 }
701
702 static void
703 controller_surface_listener_destroyed(void *data,
704                   struct ivi_controller_surface *controller)
705 {
706     struct surface_context *ctx_surf = data;
707
708     if (ctx_surf->notification != NULL) {
709         ctx_surf->notification(ctx_surf->id_surface,
710                                &ctx_surf->prop,
711                                ILM_NOTIFICATION_CONTENT_REMOVED);
712     }
713
714     wl_list_remove(&ctx_surf->link);
715     free(ctx_surf);
716 }
717
718 static void
719 controller_surface_listener_content(void *data,
720                    struct ivi_controller_surface *controller,
721                    int32_t content_state)
722 {
723     struct surface_context *ctx_surf = data;
724
725     // if client surface (=content) was removed with ilm_surfaceDestroy()
726     // the expected behavior within ILM API mandates a full removal
727     // of the surface from the scene. We must remove the controller
728     // from scene, too.
729     if (IVI_CONTROLLER_SURFACE_CONTENT_STATE_CONTENT_REMOVED == content_state)
730     {
731         if (ctx_surf->notification != NULL) {
732             ctx_surf->notification(ctx_surf->id_surface,
733                                    &ctx_surf->prop,
734                                    ILM_NOTIFICATION_CONTENT_REMOVED);
735         }
736
737         ivi_controller_surface_destroy(controller, 1);
738
739         wl_list_remove(&ctx_surf->link);
740         free(ctx_surf);
741     }
742     else if (IVI_CONTROLLER_SURFACE_CONTENT_STATE_CONTENT_AVAILABLE == content_state)
743     {
744         if (ctx_surf->notification != NULL) {
745             ctx_surf->notification(ctx_surf->id_surface,
746                                     &ctx_surf->prop,
747                                     ILM_NOTIFICATION_CONTENT_AVAILABLE);
748         }
749     }
750 }
751
752 static void
753 controller_surface_listener_input_focus(void *data,
754                    struct ivi_controller_surface *controller,
755                    uint32_t device,
756                    int32_t enabled)
757 {
758     (void)data;
759     (void)controller;
760     (void)device;
761     (void)enabled;
762 }
763
764 static struct ivi_controller_surface_listener controller_surface_listener=
765 {
766     controller_surface_listener_visibility,
767     controller_surface_listener_opacity,
768     controller_surface_listener_source_rectangle,
769     controller_surface_listener_destination_rectangle,
770     controller_surface_listener_configuration,
771     controller_surface_listener_orientation,
772     controller_surface_listener_pixelformat,
773     controller_surface_listener_layer,
774     controller_surface_listener_stats,
775     controller_surface_listener_destroyed,
776     controller_surface_listener_content,
777     controller_surface_listener_input_focus
778 };
779
780 static void
781 controller_listener_layer(void *data,
782                           struct ivi_controller *controller,
783                           uint32_t id_layer)
784 {
785    struct wayland_context *ctx = data;
786
787    if (wayland_controller_is_inside_layer_list(&ctx->list_layer, id_layer))
788    {
789       return;
790    }
791
792    (void) create_controller_layer(ctx, 0, 0, id_layer);
793 }
794
795 static void
796 controller_listener_surface(void *data,
797                             struct ivi_controller *controller,
798                             uint32_t id_surface)
799 {
800     struct wayland_context *ctx = data;
801     struct surface_context *ctx_surf = NULL;
802
803     ctx_surf = get_surface_context(ctx, id_surface);
804     if (ctx_surf != NULL) {
805         if (!ctx_surf->is_surface_creation_noticed) {
806             if (ctx_surf->notification != NULL) {
807                 ctx_surf->notification(ctx_surf->id_surface,
808                                        &ctx_surf->prop,
809                                        ILM_NOTIFICATION_CONTENT_AVAILABLE);
810                 ctx_surf->is_surface_creation_noticed = true;
811             }
812             ctx_surf->controller = ivi_controller_surface_create(
813                                        controller, id_surface);
814         }
815         else {
816             fprintf(stderr, "invalid id_surface in controller_listener_surface\n");
817         }
818         return;
819     }
820
821     ctx_surf = calloc(1, sizeof *ctx_surf);
822     if (ctx_surf == NULL) {
823         fprintf(stderr, "Failed to allocate memory for surface_context\n");
824         return;
825     }
826
827     ctx_surf->controller = ivi_controller_surface_create(
828                                controller, id_surface);
829     if (ctx_surf->controller == NULL) {
830         free(ctx_surf);
831         fprintf(stderr, "Failed to create controller surface\n");
832         return;
833     }
834     ctx_surf->id_surface = id_surface;
835     ctx_surf->prop.inputDevicesAcceptance = ILM_INPUT_DEVICE_ALL;
836     ctx_surf->ctx = ctx;
837     ctx_surf->is_surface_creation_noticed = true;
838
839     wl_list_init(&ctx_surf->link);
840     wl_list_insert(&ctx->list_surface, &ctx_surf->link);
841     wl_list_init(&ctx_surf->order.link);
842     ivi_controller_surface_add_listener(ctx_surf->controller,
843                                         &controller_surface_listener, ctx_surf);
844 }
845
846 static void
847 controller_listener_error(void *data,
848                           struct ivi_controller *ivi_controller,
849                           int32_t object_id,
850                           int32_t object_type,
851                           int32_t error_code,
852                           const char *error_text)
853 {
854     (void)data;
855     (void)ivi_controller;
856     (void)object_id;
857     (void)object_type;
858     (void)error_code;
859     (void)error_text;
860 }
861
862 static void
863 controller_listener_screen(void *data,
864                            struct ivi_controller *ivi_controller,
865                            uint32_t id_screen,
866                            struct ivi_controller_screen *controller_screen)
867 {
868     struct wayland_context *ctx = data;
869     struct screen_context *ctx_screen;
870     (void)ivi_controller;
871
872     ctx_screen = get_screen_context_by_serverid(ctx, id_screen);
873     if (ctx_screen == NULL) {
874         fprintf(stderr, "Failed to allocate memory for screen_context\n");
875         return;
876     }
877     ctx_screen->controller = controller_screen;
878 }
879
880 static struct ivi_controller_listener controller_listener= {
881     controller_listener_screen,
882     controller_listener_layer,
883     controller_listener_surface,
884     controller_listener_error
885 };
886
887 static void
888 registry_handle_control(void *data,
889                        struct wl_registry *registry,
890                        uint32_t name, const char *interface,
891                        uint32_t version)
892 {
893     struct wayland_context *ctx = data;
894     (void)version;
895
896     if (strcmp(interface, "ivi_controller") == 0) {
897         ctx->controller = wl_registry_bind(registry, name,
898                                            &ivi_controller_interface, 1);
899         if (ctx->controller == NULL) {
900             fprintf(stderr, "Failed to registry bind ivi_controller\n");
901             return;
902         }
903         if (ivi_controller_add_listener(ctx->controller,
904                                        &controller_listener,
905                                        ctx)) {
906             fprintf(stderr, "Failed to add ivi_controller listener\n");
907             return;
908         }
909     } else if (strcmp(interface, "wl_output") == 0) {
910         struct screen_context *ctx_scrn = calloc(1, sizeof *ctx_scrn);
911         struct wl_proxy *pxy = NULL;
912
913         if (ctx_scrn == NULL) {
914             fprintf(stderr, "Failed to allocate memory for screen_context\n");
915             return;
916         }
917         wl_list_init(&ctx_scrn->link);
918         ctx_scrn->output = wl_registry_bind(registry, name,
919                                            &wl_output_interface, 1);
920         if (ctx_scrn->output == NULL) {
921             free(ctx_scrn);
922             fprintf(stderr, "Failed to registry bind wl_output\n");
923             return;
924         }
925
926         if (wl_output_add_listener(ctx_scrn->output,
927                                    &output_listener,
928                                    ctx_scrn)) {
929             free(ctx_scrn);
930             fprintf(stderr, "Failed to add wl_output listener\n");
931             return;
932         }
933
934         pxy = (struct wl_proxy*)ctx_scrn->output;
935         ctx_scrn->id_from_server = wl_proxy_get_id(pxy);
936         ctx_scrn->id_screen = ctx->num_screen;
937         ctx->num_screen++;
938         wl_list_init(&ctx_scrn->order.list_layer);
939         wl_list_insert(&ctx->list_screen, &ctx_scrn->link);
940     }
941 }
942
943 static const struct wl_registry_listener
944 registry_control_listener= {
945     registry_handle_control,
946     NULL
947 };
948
949 static struct ilm_control_context ilm_context;
950
951 static void destroy_control_resources(void)
952 {
953     struct ilm_control_context *ctx = &ilm_context;
954
955     // free resources of output objects
956     if (! ctx->wl.controller) {
957         struct screen_context *ctx_scrn;
958         struct screen_context *next;
959
960         wl_list_for_each_safe(ctx_scrn, next, &ctx->wl.list_screen, link) {
961             if (ctx_scrn->output != NULL) {
962                 wl_output_destroy(ctx_scrn->output);
963             }
964
965             wl_list_remove(&ctx_scrn->link);
966             free(ctx_scrn);
967         }
968     }
969
970     if (ctx->wl.controller != NULL) {
971         {
972             struct surface_context *l;
973             struct surface_context *n;
974             wl_list_for_each_safe(l, n, &ctx->wl.list_surface, link) {
975                 wl_list_remove(&l->link);
976                 wl_list_remove(&l->order.link);
977                 ivi_controller_surface_destroy(l->controller, 0);
978                 free(l);
979             }
980         }
981
982         {
983             struct layer_context *l;
984             struct layer_context *n;
985             wl_list_for_each_safe(l, n, &ctx->wl.list_layer, link) {
986                 wl_list_remove(&l->link);
987                 wl_list_remove(&l->order.link);
988                 free(l);
989             }
990         }
991
992         {
993             struct screen_context *ctx_scrn;
994             struct screen_context *next;
995
996             wl_list_for_each_safe(ctx_scrn, next, &ctx->wl.list_screen, link) {
997                 if (ctx_scrn->output != NULL) {
998                     wl_output_destroy(ctx_scrn->output);
999                 }
1000
1001                 wl_list_remove(&ctx_scrn->link);
1002                 ivi_controller_screen_destroy(ctx_scrn->controller);
1003                 free(ctx_scrn);
1004             }
1005         }
1006
1007         ivi_controller_destroy(ctx->wl.controller);
1008         ctx->wl.controller = NULL;
1009     }
1010
1011     if (ctx->wl.display) {
1012         wl_display_flush(ctx->wl.display);
1013     }
1014
1015     if (ctx->wl.registry) {
1016         wl_registry_destroy(ctx->wl.registry);
1017         ctx->wl.registry = NULL;
1018     }
1019
1020     if (ctx->wl.queue) {
1021         wl_event_queue_destroy(ctx->wl.queue);
1022         ctx->wl.queue = NULL;
1023     }
1024
1025     if (0 != pthread_mutex_destroy(&ctx->mutex)) {
1026         fprintf(stderr, "failed to destroy pthread_mutex\n");
1027     }
1028 }
1029
1030 static void send_shutdown_event(struct ilm_control_context *ctx)
1031 {
1032     uint64_t buf = 1;
1033     while (write(ctx->shutdown_fd, &buf, sizeof buf) == -1 && errno == EINTR)
1034        ;
1035 }
1036
1037 ILM_EXPORT void
1038 ilmControl_destroy(void)
1039 {
1040     struct ilm_control_context *ctx = &ilm_context;
1041
1042     send_shutdown_event(ctx);
1043
1044     if (0 != pthread_join(ctx->thread, NULL)) {
1045         fprintf(stderr, "failed to join control thread\n");
1046     }
1047
1048     destroy_control_resources();
1049
1050     close(ctx->shutdown_fd);
1051
1052     memset(ctx, 0, sizeof *ctx);
1053 }
1054
1055 ILM_EXPORT ilmErrorTypes
1056 ilmControl_init(t_ilm_nativedisplay nativedisplay)
1057 {
1058     struct ilm_control_context *ctx = &ilm_context;
1059
1060     if (ctx->initialized)
1061     {
1062         fprintf(stderr, "Already initialized!\n");
1063         return ILM_FAILED;
1064     }
1065
1066     if (nativedisplay == 0) {
1067         return ILM_ERROR_INVALID_ARGUMENTS;
1068     }
1069
1070     ctx->shutdown_fd = -1;
1071
1072     ctx->wl.display = (struct wl_display*)nativedisplay;
1073
1074     wl_list_init(&ctx->wl.list_screen);
1075     wl_list_init(&ctx->wl.list_layer);
1076     wl_list_init(&ctx->wl.list_surface);
1077
1078     {
1079        pthread_mutexattr_t a;
1080        if (pthread_mutexattr_init(&a) != 0)
1081        {
1082           return ILM_FAILED;
1083        }
1084
1085        if (pthread_mutexattr_settype(&a, PTHREAD_MUTEX_RECURSIVE) != 0)
1086        {
1087           pthread_mutexattr_destroy(&a);
1088           return ILM_FAILED;
1089        }
1090
1091        if (pthread_mutex_init(&ctx->mutex, &a) != 0)
1092        {
1093            pthread_mutexattr_destroy(&a);
1094            fprintf(stderr, "failed to initialize pthread_mutex\n");
1095            return ILM_FAILED;
1096        }
1097
1098        pthread_mutexattr_destroy(&a);
1099     }
1100
1101     return init_control() == 0 ? ILM_SUCCESS : ILM_FAILED;
1102 }
1103
1104 static void*
1105 control_thread(void *p_ret)
1106 {
1107     struct ilm_control_context *const ctx = &ilm_context;
1108     struct wayland_context *const wl = &ctx->wl;
1109     struct wl_display *const display = wl->display;
1110     struct wl_event_queue *const queue = wl->queue;
1111     int const fd = wl_display_get_fd(display);
1112     int const shutdown_fd = ctx->shutdown_fd;
1113     (void) p_ret;
1114
1115     while (1)
1116     {
1117         while (wl_display_prepare_read_queue(display, queue) != 0)
1118         {
1119             lock_context(ctx);
1120             wl_display_dispatch_queue_pending(display, queue);
1121             unlock_context(ctx);
1122         }
1123
1124         if (wl_display_flush(display) == -1)
1125         {
1126             break;
1127         }
1128
1129         struct pollfd pfd[2] = {
1130            { .fd = fd,          .events = POLLIN },
1131            { .fd = shutdown_fd, .events = POLLIN }
1132         };
1133
1134         int pollret = poll(pfd, 2, -1);
1135         if (pollret != -1 && (pfd[0].revents & POLLIN))
1136         {
1137             wl_display_read_events(display);
1138
1139             lock_context(ctx);
1140             int ret = wl_display_dispatch_queue_pending(display, queue);
1141             unlock_context(ctx);
1142
1143             if (ret == -1)
1144             {
1145                 break;
1146             }
1147         }
1148         else
1149         {
1150             wl_display_cancel_read(display);
1151
1152             if (pollret == -1 || (pfd[1].revents & POLLIN))
1153             {
1154                 break;
1155             }
1156         }
1157     }
1158
1159     return NULL;
1160 }
1161
1162 static int
1163 init_control(void)
1164 {
1165     struct ilm_control_context *ctx = &ilm_context;
1166     struct wayland_context *wl = &ctx->wl;
1167     int wait_count = 0;
1168     int ret = 0;
1169
1170     wl_list_init(&ctx->list_nativehandle);
1171
1172     wl->queue = wl_display_create_queue(wl->display);
1173
1174     /* registry_add_listener for request by ivi-controller */
1175     wl->registry = wl_display_get_registry(wl->display);
1176     if (wl->registry == NULL) {
1177         wl_event_queue_destroy(wl->queue);
1178         wl->queue = NULL;
1179         fprintf(stderr, "Failed to get registry\n");
1180         return -1;
1181     }
1182     wl_proxy_set_queue((void*)wl->registry, wl->queue);
1183
1184     if (wl_registry_add_listener(wl->registry,
1185                              &registry_control_listener, ctx)) {
1186         fprintf(stderr, "Failed to add registry listener\n");
1187         return -1;
1188     }
1189
1190     // first level objects; ivi_controller
1191     display_roundtrip_queue(wl->display, wl->queue);
1192     // second level object: ivi_controller_surfaces/layers
1193     display_roundtrip_queue(wl->display, wl->queue);
1194     // third level objects: ivi_controller_surfaces/layers properties
1195     display_roundtrip_queue(wl->display, wl->queue);
1196
1197     if (! wl->controller)
1198     {
1199         fprintf(stderr, "ivi_controller not available\n");
1200         return -1;
1201     }
1202
1203     ctx->shutdown_fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
1204
1205     if (ctx->shutdown_fd == -1)
1206     {
1207         fprintf(stderr, "Could not setup shutdown-fd: %s\n", strerror(errno));
1208         return ILM_FAILED;
1209     }
1210
1211     ret = pthread_create(&ctx->thread, NULL, control_thread, NULL);
1212
1213     if (ret != 0) {
1214         fprintf(stderr, "Failed to start internal receive thread. returned %d\n", ret);
1215         return -1;
1216     }
1217
1218     ctx->initialized = true;
1219
1220     return 0;
1221 }
1222
1223 static ilmErrorTypes impl_sync_and_acquire_instance(struct ilm_control_context *ctx)
1224 {
1225     if (! ctx->initialized) {
1226         fprintf(stderr, "Not initialized\n");
1227         return ILM_FAILED;
1228     }
1229
1230     lock_context(ctx);
1231
1232     if (display_roundtrip_queue(ctx->wl.display, ctx->wl.queue) == -1) {
1233         int err = wl_display_get_error(ctx->wl.display);
1234         fprintf(stderr, "Error communicating with wayland: %s\n", strerror(err));
1235         unlock_context(ctx);
1236         return ILM_FAILED;
1237     }
1238
1239     return ILM_SUCCESS;
1240 }
1241
1242 #define sync_and_acquire_instance() ({ \
1243     struct ilm_control_context *ctx = &ilm_context; \
1244     { \
1245         ilmErrorTypes status = impl_sync_and_acquire_instance(ctx); \
1246         if (status != ILM_SUCCESS) { \
1247             return status; \
1248         } \
1249     } \
1250     ctx; \
1251 })
1252
1253 static void release_instance(void)
1254 {
1255     struct ilm_control_context *ctx = &ilm_context;
1256     unlock_context(ctx);
1257 }
1258
1259 static uint32_t
1260 gen_layer_id(struct ilm_control_context *ctx)
1261 {
1262     struct layer_context *ctx_layer = NULL;
1263     do {
1264         int found = 0;
1265         if (wl_list_length(&ctx->wl.list_layer) == 0) {
1266             ctx->internal_id_layer++;
1267             return ctx->internal_id_layer;
1268         }
1269         wl_list_for_each(ctx_layer, &ctx->wl.list_layer, link) {
1270             if (ctx_layer->id_layer == ctx->internal_id_layer) {
1271                 found = 1;
1272                 break;
1273             }
1274
1275             if (found == 0) {
1276                 return ctx->internal_id_layer;
1277             }
1278         }
1279         ctx->internal_id_layer++;
1280     } while(1);
1281 }
1282
1283 static struct surface_context*
1284 get_surface_context(struct wayland_context *ctx,
1285                           uint32_t id_surface)
1286 {
1287     struct surface_context *ctx_surf = NULL;
1288
1289     if (ctx->controller == NULL) {
1290         fprintf(stderr, "controller is not initialized in ilmControl\n");
1291         return NULL;
1292     }
1293
1294     wl_list_for_each(ctx_surf, &ctx->list_surface, link) {
1295         if (ctx_surf->id_surface == id_surface) {
1296             return ctx_surf;
1297         }
1298     }
1299
1300     fprintf(stderr, "failed to get surface context in ilmControl\n");
1301     return NULL;
1302 }
1303
1304 static struct screen_context*
1305 get_screen_context_by_id(struct wayland_context *ctx, uint32_t id_screen)
1306 {
1307     struct screen_context *ctx_scrn = NULL;
1308
1309     if (ctx->controller == NULL) {
1310         fprintf(stderr, "get_screen_context_by_id: controller is NULL\n");
1311         return NULL;
1312     }
1313
1314     wl_list_for_each(ctx_scrn, &ctx->list_screen, link) {
1315         if (ctx_scrn->id_screen == id_screen) {
1316             return ctx_scrn;
1317         }
1318     }
1319     return NULL;
1320 }
1321
1322 ILM_EXPORT ilmErrorTypes
1323 ilm_getPropertiesOfLayer(t_ilm_uint layerID,
1324                          struct ilmLayerProperties* pLayerProperties)
1325 {
1326     ilmErrorTypes returnValue = ILM_FAILED;
1327     struct ilm_control_context *ctx = sync_and_acquire_instance();
1328     struct layer_context *ctx_layer = NULL;
1329
1330     if (pLayerProperties != NULL) {
1331
1332         ctx_layer = (struct layer_context*)
1333                     wayland_controller_get_layer_context(
1334                         &ctx->wl, (uint32_t)layerID);
1335
1336         if (ctx_layer != NULL) {
1337             *pLayerProperties = ctx_layer->prop;
1338             returnValue = ILM_SUCCESS;
1339         }
1340     }
1341
1342     release_instance();
1343     return returnValue;
1344 }
1345
1346 static void
1347 create_layerids(struct screen_context *ctx_screen,
1348                 t_ilm_layer **layer_ids, t_ilm_uint *layer_count)
1349 {
1350     struct layer_context *ctx_layer = NULL;
1351     t_ilm_layer *ids = NULL;
1352
1353     *layer_count = wl_list_length(&ctx_screen->order.list_layer);
1354     if (*layer_count == 0) {
1355         *layer_ids = NULL;
1356         return;
1357     }
1358
1359     *layer_ids = malloc(*layer_count * sizeof(t_ilm_layer));
1360     if (*layer_ids == NULL) {
1361         fprintf(stderr, "memory insufficient for layerids\n");
1362         *layer_count = 0;
1363         return;
1364     }
1365
1366     ids = *layer_ids;
1367     wl_list_for_each_reverse(ctx_layer, &ctx_screen->order.list_layer, order.link) {
1368         *ids = (t_ilm_layer)ctx_layer->id_layer;
1369         ids++;
1370     }
1371 }
1372
1373 ILM_EXPORT ilmErrorTypes
1374 ilm_getPropertiesOfScreen(t_ilm_display screenID,
1375                               struct ilmScreenProperties* pScreenProperties)
1376 {
1377     ilmErrorTypes returnValue = ILM_FAILED;
1378
1379     if (! pScreenProperties)
1380     {
1381         return ILM_ERROR_INVALID_ARGUMENTS;
1382     }
1383
1384     struct ilm_control_context *ctx = sync_and_acquire_instance();
1385
1386     struct screen_context *ctx_screen = NULL;
1387     ctx_screen = get_screen_context_by_id(&ctx->wl, (uint32_t)screenID);
1388     if (ctx_screen != NULL) {
1389         *pScreenProperties = ctx_screen->prop;
1390         create_layerids(ctx_screen, &pScreenProperties->layerIds,
1391                                     &pScreenProperties->layerCount);
1392         returnValue = ILM_SUCCESS;
1393     }
1394
1395     release_instance();
1396     return returnValue;
1397 }
1398
1399 ILM_EXPORT ilmErrorTypes
1400 ilm_getNumberOfHardwareLayers(t_ilm_uint screenID,
1401                                   t_ilm_uint* pNumberOfHardwareLayers)
1402 {
1403     (void)screenID;
1404     /* Not supported */
1405     if (pNumberOfHardwareLayers != NULL) {
1406         *pNumberOfHardwareLayers = 0;
1407         return ILM_SUCCESS;
1408     } else {
1409         return ILM_FAILED;
1410     }
1411 }
1412
1413 ILM_EXPORT ilmErrorTypes
1414 ilm_getScreenIDs(t_ilm_uint* pNumberOfIDs, t_ilm_uint** ppIDs)
1415 {
1416     ilmErrorTypes returnValue = ILM_FAILED;
1417     struct ilm_control_context *ctx = sync_and_acquire_instance();
1418
1419     if ((pNumberOfIDs != NULL) && (ppIDs != NULL)) {
1420         struct screen_context *ctx_scrn = NULL;
1421         t_ilm_uint length = wl_list_length(&ctx->wl.list_screen);
1422         *pNumberOfIDs = 0;
1423
1424         *ppIDs = (t_ilm_uint*)malloc(length * sizeof **ppIDs);
1425         if (*ppIDs != NULL) {
1426             t_ilm_uint* ids = *ppIDs;
1427             wl_list_for_each(ctx_scrn, &ctx->wl.list_screen, link) {
1428                 *ids = ctx_scrn->id_screen;
1429                 ids++;
1430             }
1431             *pNumberOfIDs = length;
1432
1433             returnValue = ILM_SUCCESS;
1434         }
1435     }
1436
1437     release_instance();
1438     return returnValue;
1439 }
1440
1441 ILM_EXPORT ilmErrorTypes
1442 ilm_getLayerIDs(t_ilm_int* pLength, t_ilm_layer** ppArray)
1443 {
1444     ilmErrorTypes returnValue = ILM_FAILED;
1445     struct ilm_control_context *ctx = sync_and_acquire_instance();
1446
1447     if ((pLength != NULL) && (ppArray != NULL)) {
1448         struct layer_context *ctx_layer = NULL;
1449         t_ilm_uint length = wl_list_length(&ctx->wl.list_layer);
1450         *pLength = 0;
1451
1452         *ppArray = (t_ilm_layer*)malloc(length * sizeof **ppArray);
1453         if (*ppArray != NULL) {
1454             // compositor sends layers in opposite order
1455             // write ids from back to front to turn them around
1456             t_ilm_layer* ids = *ppArray;
1457             wl_list_for_each_reverse(ctx_layer, &ctx->wl.list_layer, link)
1458             {
1459                 *ids = ctx_layer->id_layer;
1460                 ++ids;
1461             }
1462             *pLength = length;
1463
1464             returnValue = ILM_SUCCESS;
1465         }
1466     }
1467
1468     release_instance();
1469     return returnValue;
1470 }
1471
1472 ILM_EXPORT ilmErrorTypes
1473 ilm_getLayerIDsOnScreen(t_ilm_uint screenId,
1474                             t_ilm_int* pLength,
1475                             t_ilm_layer** ppArray)
1476 {
1477     ilmErrorTypes returnValue = ILM_FAILED;
1478     struct ilm_control_context *ctx = sync_and_acquire_instance();
1479
1480     if ((pLength != NULL) && (ppArray != NULL)) {
1481         struct screen_context *ctx_screen = NULL;
1482         ctx_screen = get_screen_context_by_id(&ctx->wl, screenId);
1483         if (ctx_screen != NULL) {
1484             struct layer_context *ctx_layer = NULL;
1485             t_ilm_int length = wl_list_length(&ctx_screen->order.list_layer);
1486
1487             if (0 < length)
1488             {
1489                 *ppArray = (t_ilm_layer*)malloc(length * sizeof **ppArray);
1490                 if (*ppArray != NULL) {
1491                     // compositor sends layers in opposite order
1492                     // write ids from back to front to turn them around
1493                     t_ilm_layer* ids = *ppArray;
1494                     wl_list_for_each_reverse(ctx_layer, &ctx_screen->order.list_layer, order.link)
1495                     {
1496                         *ids = ctx_layer->id_layer;
1497                         ++ids;
1498                     }
1499
1500                 }
1501             }
1502             else
1503             {
1504                 *ppArray = NULL;
1505             }
1506
1507             *pLength = length;
1508             returnValue = ILM_SUCCESS;
1509         }
1510     }
1511
1512     release_instance();
1513     return returnValue;
1514 }
1515
1516 ILM_EXPORT ilmErrorTypes
1517 ilm_getSurfaceIDs(t_ilm_int* pLength, t_ilm_surface** ppArray)
1518 {
1519     ilmErrorTypes returnValue = ILM_FAILED;
1520     struct ilm_control_context *ctx = sync_and_acquire_instance();
1521
1522     if ((pLength != NULL) && (ppArray != NULL)) {
1523         struct surface_context *ctx_surf = NULL;
1524         t_ilm_uint length = wl_list_length(&ctx->wl.list_surface);
1525         *pLength = 0;
1526
1527         *ppArray = (t_ilm_surface*)malloc(length * sizeof **ppArray);
1528         if (*ppArray != NULL) {
1529             t_ilm_surface* ids = *ppArray;
1530             wl_list_for_each_reverse(ctx_surf, &ctx->wl.list_surface, link) {
1531                 *ids = ctx_surf->id_surface;
1532                 ids++;
1533             }
1534             *pLength = length;
1535
1536             returnValue = ILM_SUCCESS;
1537         }
1538     }
1539
1540     release_instance();
1541     return returnValue;
1542 }
1543
1544 ILM_EXPORT ilmErrorTypes
1545 ilm_getSurfaceIDsOnLayer(t_ilm_layer layer,
1546                              t_ilm_int* pLength,
1547                              t_ilm_surface** ppArray)
1548 {
1549     struct ilm_control_context *ctx = sync_and_acquire_instance();
1550     struct layer_context *ctx_layer = NULL;
1551     struct surface_context *ctx_surf = NULL;
1552     t_ilm_uint length = 0;
1553     t_ilm_surface* ids = NULL;
1554
1555     if ((pLength == NULL) || (ppArray == NULL)) {
1556         release_instance();
1557         return ILM_FAILED;
1558     }
1559
1560     ctx_layer = (struct layer_context*)wayland_controller_get_layer_context(
1561                     &ctx->wl, (uint32_t)layer);
1562
1563     if (ctx_layer == NULL) {
1564         release_instance();
1565         return ILM_FAILED;
1566     }
1567
1568     length = wl_list_length(&ctx_layer->order.list_surface);
1569     *ppArray = (t_ilm_surface*)malloc(length * sizeof **ppArray);
1570     if (*ppArray == NULL) {
1571         release_instance();
1572         return ILM_FAILED;
1573     }
1574
1575     ids = *ppArray;
1576     wl_list_for_each_reverse(ctx_surf, &ctx_layer->order.list_surface, order.link) {
1577         *ids = (t_ilm_surface)ctx_surf->id_surface;
1578         ids++;
1579     }
1580     *pLength = length;
1581
1582     release_instance();
1583     return ILM_SUCCESS;
1584 }
1585
1586 static int create_controller_layer(struct wayland_context *ctx, t_ilm_uint width, t_ilm_uint height, t_ilm_layer layerid)
1587 {
1588      struct layer_context *ctx_layer = calloc(1, sizeof *ctx_layer);
1589      if (ctx_layer == NULL) {
1590          fprintf(stderr, "Failed to allocate memory for layer_context\n");
1591          return -1;
1592      }
1593
1594      ctx_layer->controller = ivi_controller_layer_create(
1595                                  ctx->controller,
1596                                  layerid, width, height);
1597      if (ctx_layer->controller == NULL) {
1598          fprintf(stderr, "Failed to create layer\n");
1599          free(ctx_layer);
1600          return -1;
1601      }
1602      ctx_layer->id_layer = layerid;
1603      ctx_layer->ctx = ctx;
1604
1605      wl_list_init(&ctx_layer->link);
1606      wl_list_insert(&ctx->list_layer, &ctx_layer->link);
1607      wl_list_init(&ctx_layer->order.link);
1608      wl_list_init(&ctx_layer->order.list_surface);
1609
1610      ivi_controller_layer_add_listener(ctx_layer->controller,
1611                                    &controller_layer_listener, ctx_layer);
1612
1613      return 0;
1614 }
1615
1616 ILM_EXPORT ilmErrorTypes
1617 ilm_layerCreateWithDimension(t_ilm_layer* pLayerId,
1618                                  t_ilm_uint width,
1619                                  t_ilm_uint height)
1620 {
1621     ilmErrorTypes returnValue = ILM_FAILED;
1622     struct ilm_control_context *ctx = sync_and_acquire_instance();
1623     uint32_t layerid = 0;
1624     int32_t is_inside = 0;
1625
1626     do {
1627         if (pLayerId == NULL) {
1628             break;
1629         }
1630
1631         if (*pLayerId != INVALID_ID) {
1632             /* Return failed, if layerid is already inside list_layer */
1633             is_inside = wayland_controller_is_inside_layer_list(
1634                             &ctx->wl.list_layer, *pLayerId);
1635             if (0 != is_inside) {
1636                 fprintf(stderr, "layerid=%d is already used.\n", *pLayerId);
1637                 break;
1638             }
1639             layerid = *pLayerId;
1640         }
1641         else {
1642             /* Generate ID, if layerid is INVALID_ID */
1643             layerid = gen_layer_id(ctx);
1644             *pLayerId = layerid;
1645         }
1646
1647         if (create_controller_layer(&ctx->wl, width, height, layerid) == 0)
1648         {
1649            returnValue = ILM_SUCCESS;
1650         }
1651     } while(0);
1652
1653     release_instance();
1654     return returnValue;
1655 }
1656
1657 ILM_EXPORT ilmErrorTypes
1658 ilm_layerRemove(t_ilm_layer layerId)
1659 {
1660     ilmErrorTypes returnValue = ILM_FAILED;
1661     struct ilm_control_context *ctx = sync_and_acquire_instance();
1662     struct layer_context *ctx_layer = NULL;
1663     struct layer_context *ctx_next = NULL;
1664
1665     wl_list_for_each_safe(ctx_layer, ctx_next,
1666             &ctx->wl.list_layer, link) {
1667         if (ctx_layer->id_layer == layerId) {
1668             ivi_controller_layer_destroy(ctx_layer->controller, 1);
1669
1670             wl_list_remove(&ctx_layer->link);
1671             free(ctx_layer);
1672
1673             returnValue = ILM_SUCCESS;
1674             break;
1675         }
1676     }
1677
1678     release_instance();
1679     return returnValue;
1680 }
1681
1682 ILM_EXPORT ilmErrorTypes
1683 ilm_layerGetType(t_ilm_layer layerId, ilmLayerType* pLayerType)
1684 {
1685     if (!pLayerType)
1686     {
1687        return ILM_ERROR_INVALID_ARGUMENTS;
1688     }
1689
1690     struct ilm_control_context *ctx = sync_and_acquire_instance();
1691
1692     *pLayerType = wayland_controller_is_inside_layer_list(&ctx->wl.list_layer, layerId) ?
1693        ILM_LAYERTYPE_SOFTWARE2D :
1694        ILM_LAYERTYPE_UNKNOWN;
1695
1696     release_instance();
1697     return ILM_SUCCESS; // even if non existent?
1698 }
1699
1700 ILM_EXPORT ilmErrorTypes
1701 ilm_layerSetVisibility(t_ilm_layer layerId, t_ilm_bool newVisibility)
1702 {
1703     ilmErrorTypes returnValue = ILM_FAILED;
1704     struct ilm_control_context *ctx = sync_and_acquire_instance();
1705     struct layer_context *ctx_layer = NULL;
1706
1707     ctx_layer = (struct layer_context*)wayland_controller_get_layer_context(
1708                     &ctx->wl, (uint32_t)layerId);
1709
1710     if (ctx_layer != NULL) {
1711         uint32_t visibility = 0;
1712         if (newVisibility == ILM_TRUE) {
1713             visibility = 1;
1714         }
1715         ivi_controller_layer_set_visibility(ctx_layer->controller,
1716                                             visibility);
1717         returnValue = ILM_SUCCESS;
1718     }
1719
1720     release_instance();
1721     return returnValue;
1722 }
1723
1724 ILM_EXPORT ilmErrorTypes
1725 ilm_layerGetVisibility(t_ilm_layer layerId, t_ilm_bool *pVisibility)
1726 {
1727     ilmErrorTypes returnValue = ILM_FAILED;
1728     struct ilm_control_context *ctx = sync_and_acquire_instance();
1729
1730     if (pVisibility != NULL) {
1731         struct layer_context *ctx_layer = NULL;
1732
1733         ctx_layer = (struct layer_context*)
1734                     wayland_controller_get_layer_context(
1735                         &ctx->wl, (uint32_t)layerId);
1736
1737         if (ctx_layer != NULL) {
1738             *pVisibility = ctx_layer->prop.visibility;
1739             returnValue = ILM_SUCCESS;
1740         }
1741     }
1742
1743     release_instance();
1744     return returnValue;
1745 }
1746
1747 ILM_EXPORT ilmErrorTypes
1748 ilm_layerSetOpacity(t_ilm_layer layerId, t_ilm_float opacity)
1749 {
1750     ilmErrorTypes returnValue = ILM_FAILED;
1751     struct ilm_control_context *ctx = sync_and_acquire_instance();
1752     struct layer_context *ctx_layer = NULL;
1753
1754     ctx_layer = (struct layer_context*)wayland_controller_get_layer_context(
1755                     &ctx->wl, (uint32_t)layerId);
1756
1757     if (ctx_layer != NULL) {
1758         wl_fixed_t opacity_fixed = wl_fixed_from_double((double)opacity);
1759         ivi_controller_layer_set_opacity(ctx_layer->controller,
1760                                          opacity_fixed);
1761         returnValue = ILM_SUCCESS;
1762     }
1763
1764     release_instance();
1765     return returnValue;
1766 }
1767
1768 ILM_EXPORT ilmErrorTypes
1769 ilm_layerGetOpacity(t_ilm_layer layerId, t_ilm_float *pOpacity)
1770 {
1771     ilmErrorTypes returnValue = ILM_FAILED;
1772     struct ilm_control_context *ctx = sync_and_acquire_instance();
1773
1774     if (pOpacity != NULL) {
1775         struct layer_context *ctx_layer = NULL;
1776
1777         ctx_layer = (struct layer_context*)
1778                     wayland_controller_get_layer_context(
1779                         &ctx->wl, (uint32_t)layerId);
1780
1781         if (ctx_layer != NULL) {
1782             *pOpacity = ctx_layer->prop.opacity;
1783             returnValue = ILM_SUCCESS;
1784         }
1785     }
1786
1787     release_instance();
1788     return returnValue;
1789 }
1790
1791 ILM_EXPORT ilmErrorTypes
1792 ilm_layerSetSourceRectangle(t_ilm_layer layerId,
1793                                 t_ilm_uint x, t_ilm_uint y,
1794                                 t_ilm_uint width, t_ilm_uint height)
1795 {
1796     ilmErrorTypes returnValue = ILM_FAILED;
1797     struct ilm_control_context *ctx = sync_and_acquire_instance();
1798     struct layer_context *ctx_layer = NULL;
1799
1800     ctx_layer = (struct layer_context*)wayland_controller_get_layer_context(
1801                     &ctx->wl, (uint32_t)layerId);
1802
1803     if (ctx_layer != NULL) {
1804         ivi_controller_layer_set_source_rectangle(ctx_layer->controller,
1805                                                   (uint32_t)x,
1806                                                   (uint32_t)y,
1807                                                   (uint32_t)width,
1808                                                   (uint32_t)height);
1809         returnValue = ILM_SUCCESS;
1810     }
1811
1812     release_instance();
1813     return returnValue;
1814 }
1815
1816 ILM_EXPORT ilmErrorTypes
1817 ilm_layerSetDestinationRectangle(t_ilm_layer layerId,
1818                                  t_ilm_int x, t_ilm_int y,
1819                                  t_ilm_int width, t_ilm_int height)
1820 {
1821     ilmErrorTypes returnValue = ILM_FAILED;
1822     struct ilm_control_context *ctx = sync_and_acquire_instance();
1823     struct layer_context *ctx_layer = NULL;
1824
1825     ctx_layer = (struct layer_context*)wayland_controller_get_layer_context(
1826                     &ctx->wl, (uint32_t)layerId);
1827     if (ctx_layer != NULL) {
1828         ivi_controller_layer_set_destination_rectangle(
1829                                          ctx_layer->controller,
1830                                          (uint32_t)x, (uint32_t)y,
1831                                          (uint32_t)width,
1832                                          (uint32_t)height);
1833         returnValue = ILM_SUCCESS;
1834     }
1835
1836     release_instance();
1837     return returnValue;
1838 }
1839
1840 ILM_EXPORT ilmErrorTypes
1841 ilm_layerGetDimension(t_ilm_layer layerId, t_ilm_uint *pDimension)
1842 {
1843     ilmErrorTypes returnValue = ILM_FAILED;
1844     struct ilm_control_context *ctx = sync_and_acquire_instance();
1845     struct layer_context *ctx_layer = NULL;
1846
1847     if (pDimension != NULL) {
1848         ctx_layer = (struct layer_context*)
1849                     wayland_controller_get_layer_context(
1850                         &ctx->wl, (uint32_t)layerId);
1851         if (ctx_layer != NULL) {
1852             *pDimension = ctx_layer->prop.destWidth;
1853             *(pDimension + 1) = ctx_layer->prop.destHeight;
1854             returnValue = ILM_SUCCESS;
1855         }
1856     }
1857
1858     release_instance();
1859     return returnValue;
1860 }
1861
1862 ILM_EXPORT ilmErrorTypes
1863 ilm_layerSetDimension(t_ilm_layer layerId, t_ilm_uint *pDimension)
1864 {
1865     ilmErrorTypes returnValue = ILM_FAILED;
1866     struct ilm_control_context *ctx = sync_and_acquire_instance();
1867     struct layer_context *ctx_layer = NULL;
1868
1869     if (pDimension != NULL) {
1870         ctx_layer = (struct layer_context*)
1871                     wayland_controller_get_layer_context(
1872                         &ctx->wl, (uint32_t)layerId);
1873         if (ctx_layer != NULL) {
1874             ivi_controller_layer_set_destination_rectangle(
1875                 ctx_layer->controller,
1876                 ctx_layer->prop.destX, ctx_layer->prop.destY,
1877                 (int32_t)*pDimension, (int32_t)*(pDimension + 1));
1878             returnValue = ILM_SUCCESS;
1879         }
1880     }
1881
1882     release_instance();
1883     return returnValue;
1884 }
1885
1886 ILM_EXPORT ilmErrorTypes
1887 ilm_layerGetPosition(t_ilm_layer layerId, t_ilm_uint *pPosition)
1888 {
1889     ilmErrorTypes returnValue = ILM_FAILED;
1890     struct ilm_control_context *ctx = sync_and_acquire_instance();
1891     struct layer_context *ctx_layer = NULL;
1892
1893     if (pPosition != NULL) {
1894         ctx_layer = (struct layer_context*)
1895                     wayland_controller_get_layer_context(
1896                         &ctx->wl, (uint32_t)layerId);
1897         if (ctx_layer != NULL) {
1898             *pPosition = ctx_layer->prop.destX;
1899             *(pPosition + 1) = ctx_layer->prop.destY;
1900             returnValue = ILM_SUCCESS;
1901         }
1902     }
1903
1904     release_instance();
1905     return returnValue;
1906 }
1907
1908 ILM_EXPORT ilmErrorTypes
1909 ilm_layerSetPosition(t_ilm_layer layerId, t_ilm_uint *pPosition)
1910 {
1911     ilmErrorTypes returnValue = ILM_FAILED;
1912     struct ilm_control_context *ctx = sync_and_acquire_instance();
1913     struct layer_context *ctx_layer = NULL;
1914
1915     if (pPosition != NULL) {
1916         ctx_layer = (struct layer_context*)
1917                     wayland_controller_get_layer_context(
1918                         &ctx->wl, (uint32_t)layerId);
1919         if (ctx_layer != NULL) {
1920             ivi_controller_layer_set_destination_rectangle(
1921                 ctx_layer->controller,
1922                 (int32_t)*pPosition, (int32_t)*(pPosition + 1),
1923                 ctx_layer->prop.destWidth, ctx_layer->prop.destHeight);
1924             returnValue = ILM_SUCCESS;
1925         }
1926     }
1927
1928     release_instance();
1929     return returnValue;
1930 }
1931
1932 ILM_EXPORT ilmErrorTypes
1933 ilm_layerSetOrientation(t_ilm_layer layerId, ilmOrientation orientation)
1934 {
1935     ilmErrorTypes returnValue = ILM_FAILED;
1936     struct ilm_control_context *ctx = sync_and_acquire_instance();
1937     struct layer_context *ctx_layer = NULL;
1938     int32_t iviorientation = 0;
1939
1940     do {
1941         switch(orientation) {
1942         case ILM_ZERO:
1943             iviorientation = IVI_CONTROLLER_SURFACE_ORIENTATION_0_DEGREES;
1944             break;
1945         case ILM_NINETY:
1946             iviorientation = IVI_CONTROLLER_SURFACE_ORIENTATION_90_DEGREES;
1947             break;
1948         case ILM_ONEHUNDREDEIGHTY:
1949             iviorientation = IVI_CONTROLLER_SURFACE_ORIENTATION_180_DEGREES;
1950             break;
1951         case ILM_TWOHUNDREDSEVENTY:
1952             iviorientation = IVI_CONTROLLER_SURFACE_ORIENTATION_270_DEGREES;
1953             break;
1954         default:
1955             returnValue = ILM_ERROR_INVALID_ARGUMENTS;
1956             break;
1957         }
1958
1959         ctx_layer = (struct layer_context*)wayland_controller_get_layer_context(
1960                         &ctx->wl, (uint32_t)layerId);
1961         if (ctx_layer == NULL) {
1962             returnValue = ILM_FAILED;
1963             break;
1964         }
1965
1966         ivi_controller_layer_set_orientation(ctx_layer->controller,
1967                                              iviorientation);
1968
1969         returnValue = ILM_SUCCESS;
1970     } while(0);
1971
1972     release_instance();
1973     return returnValue;
1974 }
1975
1976 ILM_EXPORT ilmErrorTypes
1977 ilm_layerGetOrientation(t_ilm_layer layerId, ilmOrientation *pOrientation)
1978 {
1979     ilmErrorTypes returnValue = ILM_FAILED;
1980     struct ilm_control_context *ctx = sync_and_acquire_instance();
1981     struct layer_context *ctx_layer = NULL;
1982
1983     if (pOrientation != NULL) {
1984         ctx_layer = (struct layer_context*)
1985                     wayland_controller_get_layer_context(
1986                         &ctx->wl, (uint32_t)layerId);
1987         if (ctx_layer != NULL) {
1988             *pOrientation = ctx_layer->prop.orientation;
1989             returnValue = ILM_SUCCESS;
1990         }
1991     }
1992
1993     release_instance();
1994     return returnValue;
1995 }
1996
1997 ILM_EXPORT ilmErrorTypes
1998 ilm_layerSetChromaKey(t_ilm_layer layerId, t_ilm_int* pColor)
1999 {
2000     (void)layerId;
2001     (void)pColor;
2002     /* Not supported */
2003     return ILM_FAILED;
2004 }
2005
2006 ILM_EXPORT ilmErrorTypes
2007 ilm_layerSetRenderOrder(t_ilm_layer layerId,
2008                         t_ilm_surface *pSurfaceId,
2009                         t_ilm_int number)
2010 {
2011     ilmErrorTypes returnValue = ILM_FAILED;
2012     struct ilm_control_context *ctx = sync_and_acquire_instance();
2013     struct layer_context *ctx_layer = NULL;
2014
2015     ctx_layer = (struct layer_context*)wayland_controller_get_layer_context(
2016                     &ctx->wl, (uint32_t)layerId);
2017
2018     if (ctx_layer)
2019     {
2020         struct wl_array ids;
2021         wl_array_init(&ids);
2022         uint32_t *pids = wl_array_add(&ids, number * sizeof *pids);
2023         t_ilm_uint i;
2024         for (i = 0; i < number; i++) pids[i] = (uint32_t)pSurfaceId[i];
2025         ivi_controller_layer_set_render_order(ctx_layer->controller, &ids);
2026         wl_array_release(&ids);
2027         returnValue = ILM_SUCCESS;
2028     }
2029
2030     release_instance();
2031     return returnValue;
2032 }
2033
2034 ILM_EXPORT ilmErrorTypes
2035 ilm_layerGetCapabilities(t_ilm_layer layerId,
2036                          t_ilm_layercapabilities *pCapabilities)
2037 {
2038     (void)layerId;
2039     (void)pCapabilities;
2040     /* Not supported */
2041     return ILM_FAILED;
2042 }
2043
2044 ILM_EXPORT ilmErrorTypes
2045 ilm_layerTypeGetCapabilities(ilmLayerType layerType,
2046                              t_ilm_layercapabilities *pCapabilities)
2047 {
2048     (void)layerType;
2049     (void)pCapabilities;
2050     /* Not supported */
2051     return ILM_FAILED;
2052 }
2053
2054 ILM_EXPORT ilmErrorTypes
2055 ilm_surfaceSetVisibility(t_ilm_surface surfaceId, t_ilm_bool newVisibility)
2056 {
2057     ilmErrorTypes returnValue = ILM_FAILED;
2058     struct ilm_control_context *ctx = sync_and_acquire_instance();
2059     struct surface_context *ctx_surf = NULL;
2060     uint32_t visibility = 0;
2061
2062     if (newVisibility == ILM_TRUE) {
2063         visibility = 1;
2064     }
2065     ctx_surf = get_surface_context(&ctx->wl, surfaceId);
2066     if (ctx_surf) {
2067         ivi_controller_surface_set_visibility(ctx_surf->controller,
2068                                               visibility);
2069         returnValue = ILM_SUCCESS;
2070     }
2071
2072     release_instance();
2073     return returnValue;
2074 }
2075
2076 ILM_EXPORT ilmErrorTypes
2077 ilm_surfaceSetOpacity(t_ilm_surface surfaceId, t_ilm_float opacity)
2078 {
2079     ilmErrorTypes returnValue = ILM_FAILED;
2080     struct ilm_control_context *ctx = sync_and_acquire_instance();
2081     struct surface_context *ctx_surf = NULL;
2082     wl_fixed_t opacity_fixed = 0;
2083
2084     opacity_fixed = wl_fixed_from_double((double)opacity);
2085     ctx_surf = get_surface_context(&ctx->wl, surfaceId);
2086     if (ctx_surf) {
2087         ivi_controller_surface_set_opacity(ctx_surf->controller,
2088                                            opacity_fixed);
2089         returnValue = ILM_SUCCESS;
2090     }
2091
2092     release_instance();
2093     return returnValue;
2094 }
2095
2096 ILM_EXPORT ilmErrorTypes
2097 ilm_surfaceGetOpacity(t_ilm_surface surfaceId, t_ilm_float *pOpacity)
2098 {
2099     ilmErrorTypes returnValue = ILM_FAILED;
2100     struct ilm_control_context *ctx = sync_and_acquire_instance();
2101
2102     if (pOpacity != NULL) {
2103         struct surface_context *ctx_surf = NULL;
2104         ctx_surf = get_surface_context(&ctx->wl, surfaceId);
2105         if (ctx_surf) {
2106             *pOpacity = ctx_surf->prop.opacity;
2107             returnValue = ILM_SUCCESS;
2108         }
2109     }
2110
2111     release_instance();
2112     return returnValue;
2113 }
2114
2115 ILM_EXPORT ilmErrorTypes
2116 ilm_SetKeyboardFocusOn(t_ilm_surface surfaceId)
2117 {
2118     ilmErrorTypes returnValue = ILM_FAILED;
2119     (void)surfaceId;
2120     returnValue = ILM_SUCCESS;
2121     return returnValue;
2122 }
2123
2124 ILM_EXPORT ilmErrorTypes
2125 ilm_GetKeyboardFocusSurfaceId(t_ilm_surface* pSurfaceId)
2126 {
2127     ilmErrorTypes returnValue = ILM_FAILED;
2128     (void)pSurfaceId;
2129     returnValue = ILM_SUCCESS;
2130     return returnValue;
2131 }
2132
2133 ILM_EXPORT ilmErrorTypes
2134 ilm_surfaceSetDestinationRectangle(t_ilm_surface surfaceId,
2135                                    t_ilm_int x, t_ilm_int y,
2136                                    t_ilm_int width, t_ilm_int height)
2137 {
2138     ilmErrorTypes returnValue = ILM_FAILED;
2139     struct ilm_control_context *ctx = sync_and_acquire_instance();
2140     struct surface_context *ctx_surf = NULL;
2141
2142     ctx_surf = get_surface_context(&ctx->wl, surfaceId);
2143     if (ctx_surf) {
2144         ivi_controller_surface_set_destination_rectangle(
2145                                              ctx_surf->controller,
2146                                              x, y, width, height);
2147         returnValue = ILM_SUCCESS;
2148     }
2149
2150     release_instance();
2151     return returnValue;
2152 }
2153
2154 ILM_EXPORT ilmErrorTypes
2155 ilm_surfaceSetDimension(t_ilm_surface surfaceId, t_ilm_uint *pDimension)
2156 {
2157     ilmErrorTypes returnValue = ILM_FAILED;
2158     struct ilm_control_context *ctx = sync_and_acquire_instance();
2159
2160     if (pDimension != NULL) {
2161         struct surface_context *ctx_surf = NULL;
2162         ctx_surf = get_surface_context(&ctx->wl, surfaceId);
2163         if (ctx_surf) {
2164             uint32_t width = *pDimension;
2165             uint32_t height = *(pDimension + 1);
2166             ivi_controller_surface_set_destination_rectangle(
2167                 ctx_surf->controller,
2168                 ctx_surf->prop.destX, ctx_surf->prop.destY, width, height);
2169             returnValue = ILM_SUCCESS;
2170         }
2171     }
2172
2173     release_instance();
2174     return returnValue;
2175 }
2176
2177 ILM_EXPORT ilmErrorTypes
2178 ilm_surfaceGetPosition(t_ilm_surface surfaceId, t_ilm_uint *pPosition)
2179 {
2180     ilmErrorTypes returnValue = ILM_FAILED;
2181     struct ilm_control_context *ctx = sync_and_acquire_instance();
2182
2183     if (pPosition != NULL) {
2184         struct surface_context *ctx_surf = NULL;
2185         ctx_surf = get_surface_context(&ctx->wl, surfaceId);
2186         if (ctx_surf) {
2187             *pPosition = ctx_surf->prop.destX;
2188             *(pPosition + 1) = ctx_surf->prop.destY;
2189             returnValue = ILM_SUCCESS;
2190         }
2191     }
2192
2193     release_instance();
2194     return returnValue;
2195 }
2196
2197 ILM_EXPORT ilmErrorTypes
2198 ilm_surfaceSetPosition(t_ilm_surface surfaceId, t_ilm_uint *pPosition)
2199 {
2200     ilmErrorTypes returnValue = ILM_FAILED;
2201     struct ilm_control_context *ctx = sync_and_acquire_instance();
2202
2203     if (pPosition != NULL) {
2204         struct surface_context *ctx_surf = NULL;
2205         ctx_surf = get_surface_context(&ctx->wl, surfaceId);
2206         if (ctx_surf) {
2207             int32_t destX = (int32_t)*pPosition;
2208             int32_t destY = (int32_t)*(pPosition + 1);
2209             ivi_controller_surface_set_destination_rectangle(
2210                 ctx_surf->controller, destX, destY,
2211                 ctx_surf->prop.destWidth, ctx_surf->prop.destHeight);
2212             returnValue = ILM_SUCCESS;
2213         }
2214     }
2215
2216     release_instance();
2217     return returnValue;
2218 }
2219
2220 ILM_EXPORT ilmErrorTypes
2221 ilm_surfaceSetOrientation(t_ilm_surface surfaceId,
2222                               ilmOrientation orientation)
2223 {
2224     ilmErrorTypes returnValue = ILM_FAILED;
2225     struct ilm_control_context *ctx = sync_and_acquire_instance();
2226     struct surface_context *ctx_surf = NULL;
2227     int32_t iviorientation = 0;
2228
2229     do {
2230         switch(orientation) {
2231         case ILM_ZERO:
2232             iviorientation = IVI_CONTROLLER_SURFACE_ORIENTATION_0_DEGREES;
2233             break;
2234         case ILM_NINETY:
2235             iviorientation = IVI_CONTROLLER_SURFACE_ORIENTATION_90_DEGREES;
2236             break;
2237         case ILM_ONEHUNDREDEIGHTY:
2238             iviorientation = IVI_CONTROLLER_SURFACE_ORIENTATION_180_DEGREES;
2239             break;
2240         case ILM_TWOHUNDREDSEVENTY:
2241             iviorientation = IVI_CONTROLLER_SURFACE_ORIENTATION_270_DEGREES;
2242             break;
2243         default:
2244             returnValue = ILM_ERROR_INVALID_ARGUMENTS;
2245             break;
2246         }
2247
2248         ctx_surf = get_surface_context(&ctx->wl, surfaceId);
2249         if (ctx_surf == NULL) {
2250             returnValue = ILM_FAILED;
2251             break;
2252         }
2253
2254         ivi_controller_surface_set_orientation(ctx_surf->controller,
2255                                                iviorientation);
2256
2257         returnValue = ILM_SUCCESS;
2258     } while(0);
2259
2260     release_instance();
2261     return returnValue;
2262 }
2263
2264 ILM_EXPORT ilmErrorTypes
2265 ilm_surfaceGetOrientation(t_ilm_surface surfaceId,
2266                               ilmOrientation *pOrientation)
2267 {
2268     ilmErrorTypes returnValue = ILM_FAILED;
2269     struct ilm_control_context *ctx = sync_and_acquire_instance();
2270
2271     if (pOrientation != NULL) {
2272         struct surface_context *ctx_surf = NULL;
2273         ctx_surf = get_surface_context(&ctx->wl, surfaceId);
2274         if (ctx_surf) {
2275             *pOrientation = ctx_surf->prop.orientation;
2276             returnValue = ILM_SUCCESS;
2277         }
2278     }
2279
2280     release_instance();
2281     return returnValue;
2282 }
2283
2284 ILM_EXPORT ilmErrorTypes
2285 ilm_surfaceGetPixelformat(t_ilm_layer surfaceId,
2286                               ilmPixelFormat *pPixelformat)
2287 {
2288     ilmErrorTypes returnValue = ILM_FAILED;
2289     struct ilm_control_context *ctx = sync_and_acquire_instance();
2290
2291     if (pPixelformat != NULL) {
2292         struct surface_context *ctx_surf = NULL;
2293         ctx_surf = get_surface_context(&ctx->wl, surfaceId);
2294         if (ctx_surf) {
2295             *pPixelformat = ctx_surf->prop.pixelformat;
2296             returnValue = ILM_SUCCESS;
2297         }
2298     }
2299
2300     release_instance();
2301     return returnValue;
2302 }
2303
2304 ILM_EXPORT ilmErrorTypes
2305 ilm_surfaceSetChromaKey(t_ilm_surface surfaceId, t_ilm_int* pColor)
2306 {
2307     (void)surfaceId;
2308     (void)pColor;
2309     /* Not supported */
2310     return ILM_FAILED;
2311 }
2312
2313 ILM_EXPORT ilmErrorTypes
2314 ilm_displaySetRenderOrder(t_ilm_display display,
2315                           t_ilm_layer *pLayerId, const t_ilm_uint number)
2316 {
2317     ilmErrorTypes returnValue = ILM_FAILED;
2318     struct ilm_control_context *ctx = sync_and_acquire_instance();
2319     struct screen_context *ctx_scrn = NULL;
2320
2321     ctx_scrn = get_screen_context_by_id(&ctx->wl, (uint32_t)display);
2322     if (ctx_scrn != NULL) {
2323         struct wl_array ids;
2324         wl_array_init(&ids);
2325         uint32_t *pids = wl_array_add(&ids, number * sizeof *pids);
2326         t_ilm_uint i;
2327         for (i = 0; i < number; i++) pids[i] = (uint32_t)pLayerId[i];
2328         ivi_controller_screen_set_render_order(ctx_scrn->controller, &ids);
2329         wl_array_release(&ids);
2330         returnValue = ILM_SUCCESS;
2331     }
2332
2333     release_instance();
2334     return returnValue;
2335 }
2336
2337 ILM_EXPORT ilmErrorTypes
2338 ilm_takeScreenshot(t_ilm_uint screen, t_ilm_const_string filename)
2339 {
2340     ilmErrorTypes returnValue = ILM_FAILED;
2341     struct ilm_control_context *ctx = sync_and_acquire_instance();
2342     struct screen_context *ctx_scrn = NULL;
2343
2344     ctx_scrn = get_screen_context_by_id(&ctx->wl, (uint32_t)screen);
2345     if (ctx_scrn != NULL) {
2346         ivi_controller_screen_screenshot(ctx_scrn->controller,
2347                                         filename);
2348         wl_display_flush(ctx->wl.display);
2349         returnValue = ILM_SUCCESS;
2350     }
2351
2352     release_instance();
2353     return returnValue;
2354 }
2355
2356 ILM_EXPORT ilmErrorTypes
2357 ilm_takeLayerScreenshot(t_ilm_const_string filename, t_ilm_layer layerid)
2358 {
2359     ilmErrorTypes returnValue = ILM_FAILED;
2360     struct ilm_control_context *ctx = sync_and_acquire_instance();
2361     struct layer_context *ctx_layer = NULL;
2362
2363     ctx_layer = (struct layer_context*)wayland_controller_get_layer_context(
2364                     &ctx->wl, (uint32_t)layerid);
2365     if (ctx_layer != NULL) {
2366         ivi_controller_layer_screenshot(ctx_layer->controller,
2367                                         filename);
2368         wl_display_flush(ctx->wl.display);
2369         returnValue = ILM_SUCCESS;
2370     }
2371
2372     release_instance();
2373     return returnValue;
2374 }
2375
2376 ILM_EXPORT ilmErrorTypes
2377 ilm_takeSurfaceScreenshot(t_ilm_const_string filename,
2378                               t_ilm_surface surfaceid)
2379 {
2380     ilmErrorTypes returnValue = ILM_FAILED;
2381     struct ilm_control_context *ctx = sync_and_acquire_instance();
2382     struct surface_context *ctx_surf = NULL;
2383
2384     ctx_surf = get_surface_context(&ctx->wl, (uint32_t)surfaceid);
2385     if (ctx_surf) {
2386         ivi_controller_surface_screenshot(ctx_surf->controller,
2387                                           filename);
2388         wl_display_flush(ctx->wl.display);
2389         returnValue = ILM_SUCCESS;
2390     }
2391
2392     release_instance();
2393     return returnValue;
2394 }
2395
2396 ILM_EXPORT ilmErrorTypes
2397 ilm_SetOptimizationMode(ilmOptimization id, ilmOptimizationMode mode)
2398 {
2399     (void)id;
2400     (void)mode;
2401     /* Not supported */
2402     return ILM_FAILED;
2403 }
2404
2405 ILM_EXPORT ilmErrorTypes
2406 ilm_GetOptimizationMode(ilmOptimization id, ilmOptimizationMode* pMode)
2407 {
2408     (void)id;
2409     (void)pMode;
2410     /* Not supported */
2411     return ILM_FAILED;
2412 }
2413
2414 ILM_EXPORT ilmErrorTypes
2415 ilm_layerAddNotification(t_ilm_layer layer,
2416                              layerNotificationFunc callback)
2417 {
2418     ilmErrorTypes returnValue = ILM_FAILED;
2419     struct ilm_control_context *ctx = sync_and_acquire_instance();
2420     struct layer_context *ctx_layer = NULL;
2421
2422     ctx_layer = (struct layer_context*)wayland_controller_get_layer_context(
2423                     &ctx->wl, (uint32_t)layer);
2424     if (ctx_layer == NULL) {
2425         returnValue = ILM_ERROR_INVALID_ARGUMENTS;
2426     } else {
2427         ctx_layer->notification = callback;
2428
2429         returnValue = ILM_SUCCESS;
2430     }
2431
2432     release_instance();
2433     return returnValue;
2434 }
2435
2436 ILM_EXPORT ilmErrorTypes
2437 ilm_layerRemoveNotification(t_ilm_layer layer)
2438 {
2439    return ilm_layerAddNotification(layer, NULL);
2440 }
2441
2442 ILM_EXPORT ilmErrorTypes
2443 ilm_surfaceAddNotification(t_ilm_surface surface,
2444                              surfaceNotificationFunc callback)
2445 {
2446     ilmErrorTypes returnValue = ILM_FAILED;
2447     struct ilm_control_context *ctx = sync_and_acquire_instance();
2448     struct surface_context *ctx_surf = NULL;
2449
2450     ctx_surf = (struct surface_context*)get_surface_context(
2451                     &ctx->wl, (uint32_t)surface);
2452     if (ctx_surf == NULL) {
2453         if (callback != NULL) {
2454             callback((uint32_t)surface, NULL, ILM_NOTIFICATION_CONTENT_REMOVED);
2455             controller_listener_surface(ctx, ctx->wl.controller, (uint32_t)surface);
2456             ctx_surf = (struct surface_context*)get_surface_context(
2457                         &ctx->wl, (uint32_t)surface);
2458             ctx_surf->is_surface_creation_noticed = false;
2459         }
2460     }
2461
2462     if (ctx_surf == NULL) {
2463         returnValue = ILM_ERROR_INVALID_ARGUMENTS;
2464     }
2465     else {
2466         ctx_surf->notification = callback;
2467
2468         returnValue = ILM_SUCCESS;
2469     }
2470
2471     release_instance();
2472     return returnValue;
2473 }
2474
2475 ILM_EXPORT ilmErrorTypes
2476 ilm_surfaceRemoveNotification(t_ilm_surface surface)
2477 {
2478     return ilm_surfaceAddNotification(surface, NULL);
2479 }
2480
2481 ILM_EXPORT ilmErrorTypes
2482 ilm_getNativeHandle(t_ilm_uint pid, t_ilm_int *n_handle,
2483                         t_ilm_nativehandle **p_handles)
2484 {
2485     struct ilm_control_context *ctx = sync_and_acquire_instance();
2486     struct nativehandle_context *p_nh_ctx = NULL;
2487
2488     *n_handle = 0;
2489     *p_handles = NULL;
2490
2491     wl_list_for_each(p_nh_ctx, &ctx->list_nativehandle, link)
2492     {
2493         if (p_nh_ctx->pid == pid)
2494         {
2495             *n_handle = 1;
2496             *p_handles =
2497                  (t_ilm_nativehandle*)malloc(sizeof(t_ilm_nativehandle));
2498             (*p_handles)[0] = p_nh_ctx->nativehandle;
2499             break;
2500         }
2501     }
2502
2503     release_instance();
2504     return (*n_handle > 0) ? ILM_SUCCESS : ILM_FAILED;
2505 }
2506
2507 ILM_EXPORT ilmErrorTypes
2508 ilm_getPropertiesOfSurface(t_ilm_uint surfaceID,
2509                         struct ilmSurfaceProperties* pSurfaceProperties)
2510 {
2511     ilmErrorTypes returnValue = ILM_FAILED;
2512     struct ilm_control_context *ctx = sync_and_acquire_instance();
2513
2514     if (pSurfaceProperties != NULL) {
2515         struct surface_context *ctx_surf = NULL;
2516
2517         ctx_surf = get_surface_context(&ctx->wl, (uint32_t)surfaceID);
2518         if (ctx_surf != NULL) {
2519
2520             *pSurfaceProperties = ctx_surf->prop;
2521             returnValue = ILM_SUCCESS;
2522         }
2523     }
2524
2525     release_instance();
2526     return returnValue;
2527 }
2528
2529 ILM_EXPORT ilmErrorTypes
2530 ilm_layerAddSurface(t_ilm_layer layerId,
2531                         t_ilm_surface surfaceId)
2532 {
2533     ilmErrorTypes returnValue = ILM_FAILED;
2534     struct ilm_control_context *ctx = sync_and_acquire_instance();
2535     struct layer_context *ctx_layer = NULL;
2536     struct surface_context *ctx_surf = NULL;
2537
2538     ctx_layer = (struct layer_context*)wayland_controller_get_layer_context(
2539                     &ctx->wl, (uint32_t)layerId);
2540     ctx_surf = get_surface_context(&ctx->wl, (uint32_t)surfaceId);
2541     if ((ctx_layer != NULL) && (ctx_surf != NULL)) {
2542         ivi_controller_layer_add_surface(ctx_layer->controller,
2543                                          ctx_surf->controller);
2544         returnValue = ILM_SUCCESS;
2545     }
2546
2547     release_instance();
2548     return returnValue;
2549 }
2550
2551 ILM_EXPORT ilmErrorTypes
2552 ilm_layerRemoveSurface(t_ilm_layer layerId,
2553                            t_ilm_surface surfaceId)
2554 {
2555     ilmErrorTypes returnValue = ILM_FAILED;
2556     struct ilm_control_context *ctx = sync_and_acquire_instance();
2557     struct layer_context *ctx_layer = NULL;
2558     struct surface_context *ctx_surf = NULL;
2559
2560     ctx_layer = (struct layer_context*)wayland_controller_get_layer_context(
2561                     &ctx->wl, (uint32_t)layerId);
2562     ctx_surf = get_surface_context(&ctx->wl, (uint32_t)surfaceId);
2563     if ((ctx_layer != NULL) && (ctx_surf != NULL)) {
2564         ivi_controller_layer_remove_surface(ctx_layer->controller,
2565                                             ctx_surf->controller);
2566         returnValue = ILM_SUCCESS;
2567     }
2568
2569     release_instance();
2570     return returnValue;
2571 }
2572
2573 ILM_EXPORT ilmErrorTypes
2574 ilm_surfaceGetDimension(t_ilm_surface surfaceId,
2575                             t_ilm_uint *pDimension)
2576 {
2577     ilmErrorTypes returnValue = ILM_FAILED;
2578     struct ilm_control_context *ctx = sync_and_acquire_instance();
2579
2580     if (pDimension != NULL) {
2581         struct surface_context *ctx_surf = NULL;
2582
2583         ctx_surf = get_surface_context(&ctx->wl, (uint32_t)surfaceId);
2584         if (ctx_surf != NULL) {
2585             *pDimension = (t_ilm_uint)ctx_surf->prop.destWidth;
2586             *(pDimension + 1) = (t_ilm_uint)ctx_surf->prop.destHeight;
2587             returnValue = ILM_SUCCESS;
2588         }
2589     }
2590
2591     release_instance();
2592     return returnValue;
2593 }
2594
2595 ILM_EXPORT ilmErrorTypes
2596 ilm_surfaceGetVisibility(t_ilm_surface surfaceId,
2597                              t_ilm_bool *pVisibility)
2598 {
2599     ilmErrorTypes returnValue = ILM_FAILED;
2600     struct ilm_control_context *ctx = sync_and_acquire_instance();
2601     struct surface_context *ctx_surf = NULL;
2602
2603     if (pVisibility != NULL) {
2604         ctx_surf = get_surface_context(&ctx->wl, (uint32_t)surfaceId);
2605         if (ctx_surf != NULL) {
2606             *pVisibility = (t_ilm_bool)ctx_surf->prop.visibility;
2607             returnValue = ILM_SUCCESS;
2608         }
2609     }
2610
2611     release_instance();
2612     return returnValue;
2613 }
2614
2615 ILM_EXPORT ilmErrorTypes
2616 ilm_surfaceSetSourceRectangle(t_ilm_surface surfaceId,
2617                                   t_ilm_int x, t_ilm_int y,
2618                                   t_ilm_int width, t_ilm_int height)
2619 {
2620     ilmErrorTypes returnValue = ILM_FAILED;
2621     struct ilm_control_context *ctx = sync_and_acquire_instance();
2622     struct surface_context *ctx_surf = NULL;
2623
2624     ctx_surf = get_surface_context(&ctx->wl, (uint32_t)surfaceId);
2625     if (ctx_surf != NULL) {
2626         if (ctx_surf->controller != NULL) {
2627             ivi_controller_surface_set_source_rectangle(
2628                     ctx_surf->controller,
2629                     x, y, width, height);
2630             returnValue = ILM_SUCCESS;
2631         }
2632     }
2633
2634     release_instance();
2635     return returnValue;
2636 }
2637
2638 ILM_EXPORT ilmErrorTypes
2639 ilm_commitChanges(void)
2640 {
2641     ilmErrorTypes returnValue = ILM_FAILED;
2642     struct ilm_control_context *ctx = sync_and_acquire_instance();
2643
2644     if (ctx->wl.controller != NULL) {
2645         ivi_controller_commit_changes(ctx->wl.controller);
2646
2647         if (display_roundtrip_queue(ctx->wl.display, ctx->wl.queue) != -1)
2648         {
2649             returnValue = ILM_SUCCESS;
2650         }
2651     }
2652
2653     release_instance();
2654
2655     return returnValue;
2656 }