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 <unistd.h>
23 #include <signal.h>
24 #include <poll.h>
25 #include "ilm_client.h"
26 #include "ilm_client_platform.h"
27 #include "wayland-util.h"
28 #include "ivi-application-client-protocol.h"
29 static ilmErrorTypes wayland_surfaceCreate(t_ilm_nativehandle nativehandle,
30 t_ilm_int width, t_ilm_int height,
31 ilmPixelFormat pixelFormat,
32 t_ilm_surface* pSurfaceId);
33 static ilmErrorTypes wayland_surfaceRemove(const t_ilm_surface surfaceId);
34 static ilmErrorTypes wayland_init(t_ilm_nativedisplay nativedisplay);
35 static ilmErrorTypes wayland_destroy(void);
36
37 ILM_CLIENT_PLATFORM_FUNC gIlmClientPlatformFunc;
38
init_ilmClientPlatformTable(void)39 void init_ilmClientPlatformTable(void)
40 {
41 gIlmClientPlatformFunc.surfaceCreate =
42 wayland_surfaceCreate;
43 gIlmClientPlatformFunc.surfaceRemove =
44 wayland_surfaceRemove;
45 gIlmClientPlatformFunc.init =
46 wayland_init;
47 gIlmClientPlatformFunc.destroy =
48 wayland_destroy;
49 }
50
51 struct surface_context {
52 struct ivi_surface *surface;
53 t_ilm_uint id_surface;
54 struct ilmSurfaceProperties prop;
55
56 struct wl_list link;
57 };
58
59 struct ilm_client_context {
60 int32_t valid;
61 struct wl_display *display;
62 struct wl_registry *registry;
63 struct wl_compositor *compositor;
64 struct ivi_application *ivi_application;
65 struct wl_event_queue *queue;
66
67 struct wl_list list_surface;
68
69 uint32_t internal_id_surface;
70 uint32_t name_controller;
71 };
72
73 static void
wayland_client_init(struct ilm_client_context * ctx)74 wayland_client_init(struct ilm_client_context *ctx)
75 {
76 ctx->internal_id_surface = 0;
77 }
78
79 static uint32_t
wayland_client_gen_surface_id(struct ilm_client_context * ctx)80 wayland_client_gen_surface_id(struct ilm_client_context *ctx)
81 {
82 struct surface_context *ctx_surf = NULL;
83 do {
84 int found = 0;
85 if (wl_list_length(&ctx->list_surface) == 0) {
86 ctx->internal_id_surface++;
87 return ctx->internal_id_surface;
88 }
89 wl_list_for_each(ctx_surf, &ctx->list_surface, link) {
90 if (ctx_surf->id_surface == ctx->internal_id_surface) {
91 found = 1;
92 break;
93 }
94
95 if (found == 0) {
96 return ctx->internal_id_surface;
97 }
98 }
99 ctx->internal_id_surface++;
100 } while(1);
101 }
102
103 static void
registry_handle_client(void * data,struct wl_registry * registry,uint32_t name,const char * interface,uint32_t version)104 registry_handle_client(void *data, struct wl_registry *registry,
105 uint32_t name, const char *interface,
106 uint32_t version)
107 {
108 struct ilm_client_context *ctx = data;
109 (void)version;
110
111 if (strcmp(interface, "ivi_application") == 0) {
112 ctx->ivi_application = wl_registry_bind(registry, name,
113 &ivi_application_interface, 1);
114 if (ctx->ivi_application == NULL) {
115 fprintf(stderr, "Failed to registry bind ivi_application\n");
116 return;
117 }
118 }
119 }
120
121 static void
registry_handle_client_remove(void * data,struct wl_registry * registry,uint32_t name)122 registry_handle_client_remove(void *data, struct wl_registry *registry, uint32_t name)
123 {
124 }
125
126 static const struct wl_registry_listener registry_client_listener = {
127 registry_handle_client,
128 registry_handle_client_remove
129 };
130
131 static struct ilm_client_context ilm_context = {0};
132
133 static void
134 destroy_client_resouses(void);
135
136 static ilmErrorTypes
wayland_destroy(void)137 wayland_destroy(void)
138 {
139 struct ilm_client_context *ctx = &ilm_context;
140 if (ctx->valid)
141 {
142 destroy_client_resouses();
143 ctx->valid = 0;
144
145 }
146
147 return ILM_SUCCESS;
148 }
149
150 static void
destroy_client_resouses(void)151 destroy_client_resouses(void)
152 {
153 struct ilm_client_context *ctx = &ilm_context;
154
155 {
156 struct surface_context *c = NULL;
157 struct surface_context *n = NULL;
158 wl_list_for_each_safe(c, n, &ctx->list_surface, link) {
159 wl_list_remove(&c->link);
160 ivi_surface_destroy(c->surface);
161 free(c);
162 }
163 }
164
165 if (ctx->ivi_application != NULL) {
166 ivi_application_destroy(ctx->ivi_application);
167 ctx->ivi_application = NULL;
168 }
169
170 if (ctx->queue)
171 {
172 wl_event_queue_destroy(ctx->queue);
173 ctx->queue = NULL;
174 }
175
176 if (ctx->registry)
177 {
178 wl_registry_destroy(ctx->registry);
179 ctx->registry = NULL;
180 }
181 }
182
183 static ilmErrorTypes
wayland_init(t_ilm_nativedisplay nativedisplay)184 wayland_init(t_ilm_nativedisplay nativedisplay)
185 {
186 struct ilm_client_context *ctx = &ilm_context;
187 memset(ctx, 0, sizeof *ctx);
188
189 wayland_client_init(ctx);
190 ctx->display = (struct wl_display*)nativedisplay;
191
192 return ILM_SUCCESS;
193 }
194
195 static void
init_client(void)196 init_client(void)
197 {
198 struct ilm_client_context *ctx = &ilm_context;
199
200 if (ctx->display == NULL) {
201 ctx->display = wl_display_connect(NULL);
202 }
203
204 wl_list_init(&ctx->list_surface);
205
206 ctx->queue = wl_display_create_queue(ctx->display);
207 ctx->registry = wl_display_get_registry(ctx->display);
208 if (ctx->registry == NULL) {
209 wl_event_queue_destroy(ctx->queue);
210 fprintf(stderr, "Failed to get registry\n");
211 return;
212 }
213
214 wl_proxy_set_queue((void*)ctx->registry, ctx->queue);
215 if (wl_registry_add_listener(ctx->registry,
216 ®istry_client_listener, ctx)) {
217 fprintf(stderr, "Failed to add registry listener\n");
218 return;
219 }
220 wl_display_roundtrip_queue(ctx->display, ctx->queue);
221
222 if ((ctx->display == NULL) || (ctx->ivi_application == NULL)) {
223 fprintf(stderr, "Failed to connect display at ilm_client\n");
224 return;
225 }
226
227 ctx->valid = 1;
228 }
229
230 static struct ilm_client_context*
get_client_instance(void)231 get_client_instance(void)
232 {
233 struct ilm_client_context *ctx = &ilm_context;
234 if (ctx->valid == 0) {
235 init_client();
236 }
237
238 if (ctx->valid < 0) {
239 exit(0);
240 }
241
242 wl_display_roundtrip_queue(ctx->display, ctx->queue);
243
244 return ctx;
245 }
246
247 static void
create_client_surface(struct ilm_client_context * ctx,uint32_t id_surface,struct ivi_surface * surface)248 create_client_surface(struct ilm_client_context *ctx,
249 uint32_t id_surface,
250 struct ivi_surface *surface)
251 {
252 struct surface_context *ctx_surf = NULL;
253
254 ctx_surf = calloc(1, sizeof *ctx_surf);
255 if (ctx_surf == NULL) {
256 fprintf(stderr, "Failed to allocate memory for surface_context\n");
257 return;
258 }
259
260 ctx_surf->surface = surface;
261 ctx_surf->id_surface = id_surface;
262 wl_list_insert(&ctx->list_surface, &ctx_surf->link);
263 }
264
265 static ilmErrorTypes
wayland_surfaceCreate(t_ilm_nativehandle nativehandle,t_ilm_int width,t_ilm_int height,ilmPixelFormat pixelFormat,t_ilm_surface * pSurfaceId)266 wayland_surfaceCreate(t_ilm_nativehandle nativehandle,
267 t_ilm_int width,
268 t_ilm_int height,
269 ilmPixelFormat pixelFormat,
270 t_ilm_surface* pSurfaceId)
271 {
272 ilmErrorTypes returnValue = ILM_FAILED;
273 struct ilm_client_context *ctx = get_client_instance();
274 uint32_t surfaceid = 0;
275 struct ivi_surface *surf = NULL;
276 (void)pixelFormat;
277 (void)width;
278 (void)height;
279
280 if (nativehandle == 0) {
281 return returnValue;
282 }
283
284 if (pSurfaceId != NULL) {
285 if (*pSurfaceId == INVALID_ID) {
286 surfaceid =
287 wayland_client_gen_surface_id(ctx);
288 }
289 else {
290 surfaceid = *pSurfaceId;
291 }
292
293 surf = ivi_application_surface_create(ctx->ivi_application, surfaceid,
294 (struct wl_surface*)nativehandle);
295
296 if (surf != NULL) {
297 create_client_surface(ctx, surfaceid, surf);
298 *pSurfaceId = surfaceid;
299 returnValue = ILM_SUCCESS;
300 }
301 else {
302 fprintf(stderr, "Failed to create ivi_surface\n");
303 }
304 }
305
306 return returnValue;
307 }
308
309 static ilmErrorTypes
wayland_surfaceRemove(t_ilm_surface surfaceId)310 wayland_surfaceRemove(t_ilm_surface surfaceId)
311 {
312 struct ilm_client_context *ctx = get_client_instance();
313 struct surface_context *ctx_surf = NULL;
314 struct surface_context *ctx_next = NULL;
315
316 wl_list_for_each_safe(ctx_surf, ctx_next,
317 &ctx->list_surface,
318 link) {
319 if (ctx_surf->id_surface == surfaceId) {
320 ivi_surface_destroy(ctx_surf->surface);
321 wl_list_remove(&ctx_surf->link);
322 free(ctx_surf);
323 break;
324 }
325 }
326
327 return ILM_SUCCESS;
328 }
329