1 /*
2 * Copyright (C) 2015 Advanced Driver Information Technology Joint Venture GmbH
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <sys/mman.h>
30 #include <assert.h>
31 #include <pthread.h>
32 #include <signal.h>
33 #include <poll.h>
34
35 #include <wayland-cursor.h>
36 #include <ivi-application-client-protocol.h>
37
38 #ifdef LIBWESTON_DEBUG_PROTOCOL
39 #include "dlt_common.h"
40 #include "dlt_user.h"
41 #include "weston-debug-client-protocol.h"
42
43 #define WESTON_DLT_APP_DESC "messages from weston debug protocol"
44 #define WESTON_DLT_CONTEXT_DESC "weston debug context"
45
46 #define WESTON_DLT_APP "WESN"
47 #define WESTON_DLT_CONTEXT "WESC"
48
49 #define MAXSTRLEN 1024
50 #endif
51
52 #ifndef MIN
53 #define MIN(x,y) (((x) < (y)) ? (x) : (y))
54 #endif
55
56 static int running = 1;
57
58 typedef struct _BkGndSettings
59 {
60 uint32_t surface_id;
61 uint32_t surface_width;
62 uint32_t surface_height;
63 uint32_t surface_stride;
64 }BkGndSettingsStruct;
65
66 typedef struct _WaylandContext {
67 struct wl_display *wl_display;
68 struct wl_registry *wl_registry;
69 struct wl_compositor *wl_compositor;
70 struct wl_shm *wl_shm;
71 struct wl_seat *wl_seat;
72 struct wl_pointer *wl_pointer;
73 struct wl_surface *wl_pointer_surface;
74 struct ivi_application *ivi_application;
75 BkGndSettingsStruct *bkgnd_settings;
76 struct wl_surface *wlBkgndSurface;
77 struct ivi_surface *ivi_surf;
78 struct wl_buffer *wlBkgndBuffer;
79 struct wl_cursor_theme *cursor_theme;
80 struct wl_cursor *cursor;
81 void *bkgnddata;
82 uint32_t formats;
83 #ifdef LIBWESTON_DEBUG_PROTOCOL
84 struct weston_debug_v1 *debug_iface;
85 struct wl_list stream_list;
86 int debug_fd;
87 char thread_running;
88 pthread_t dlt_ctx_thread;
89 int pipefd[2];
90 #endif
91 uint8_t enable_cursor;
92 }WaylandContextStruct;
93
94 struct debug_stream {
95 struct wl_list link;
96 int should_bind;
97 char *name;
98 struct weston_debug_stream_v1 *obj;
99 };
100
101 static const char *left_ptrs[] = {
102 "left_ptr",
103 "default",
104 "top_left_arrow",
105 "left-arrow"
106 };
107
108 static BkGndSettingsStruct*
get_bkgnd_settings_cursor_info(WaylandContextStruct * wlcontext)109 get_bkgnd_settings_cursor_info(WaylandContextStruct* wlcontext)
110 {
111 BkGndSettingsStruct* bkgnd_settings;
112 char *option;
113 char *end;
114
115 option = getenv("IVI_CLIENT_ENABLE_CURSOR");
116 if(option)
117 wlcontext->enable_cursor = (uint8_t)strtol(option, &end, 0);
118 else
119 wlcontext->enable_cursor = 0;
120
121 bkgnd_settings =
122 (BkGndSettingsStruct*)calloc(1, sizeof(BkGndSettingsStruct));
123
124 option = getenv("IVI_CLIENT_SURFACE_ID");
125 if(option)
126 bkgnd_settings->surface_id = strtol(option, &end, 0);
127 else
128 bkgnd_settings->surface_id = 10;
129
130 bkgnd_settings->surface_width = 1;
131 bkgnd_settings->surface_height = 1;
132 bkgnd_settings->surface_stride = bkgnd_settings->surface_width * 4;
133
134 return bkgnd_settings;
135 }
136
137 #ifdef LIBWESTON_DEBUG_PROTOCOL
138 static struct debug_stream *
stream_alloc(WaylandContextStruct * wlcontext,const char * name)139 stream_alloc(WaylandContextStruct* wlcontext, const char *name)
140 {
141 struct debug_stream *stream;
142
143 stream = calloc(1, (sizeof *stream));
144 if (!stream)
145 return NULL;
146
147 stream->name = strdup(name);
148 if (!stream->name) {
149 free(stream);
150 return NULL;
151 }
152
153 stream->should_bind = 0;
154
155 wl_list_insert(wlcontext->stream_list.prev, &stream->link);
156
157 return stream;
158 }
159
160 static void
stream_destroy(struct debug_stream * stream)161 stream_destroy(struct debug_stream *stream)
162 {
163 if (stream->obj)
164 weston_debug_stream_v1_destroy(stream->obj);
165
166 wl_list_remove(&stream->link);
167 free(stream->name);
168 free(stream);
169 }
170
171 static void
destroy_streams(WaylandContextStruct * wlcontext)172 destroy_streams(WaylandContextStruct* wlcontext)
173 {
174 struct debug_stream *stream;
175 struct debug_stream *tmp;
176
177 wl_list_for_each_safe(stream, tmp, &wlcontext->stream_list, link) {
178 stream_destroy(stream);
179 }
180 }
181
182 static void
handle_stream_complete(void * data,struct weston_debug_stream_v1 * obj)183 handle_stream_complete(void *data, struct weston_debug_stream_v1 *obj)
184 {
185 struct debug_stream *stream = data;
186
187 assert(stream->obj == obj);
188
189 stream_destroy(stream);
190 }
191
192 static void
handle_stream_failure(void * data,struct weston_debug_stream_v1 * obj,const char * msg)193 handle_stream_failure(void *data, struct weston_debug_stream_v1 *obj,
194 const char *msg)
195 {
196 struct debug_stream *stream = data;
197
198 assert(stream->obj == obj);
199
200 fprintf(stderr, "Debug stream '%s' aborted: %s\n", stream->name, msg);
201
202 stream_destroy(stream);
203 }
204
205 static const struct weston_debug_stream_v1_listener stream_listener = {
206 handle_stream_complete,
207 handle_stream_failure
208 };
209
210 static void
start_streams(WaylandContextStruct * wlcontext)211 start_streams(WaylandContextStruct* wlcontext)
212 {
213 struct debug_stream *stream;
214
215 wl_list_for_each(stream, &wlcontext->stream_list, link) {
216 if (stream->should_bind) {
217 stream->obj = weston_debug_v1_subscribe(wlcontext->debug_iface,
218 stream->name,
219 wlcontext->debug_fd);
220 weston_debug_stream_v1_add_listener(stream->obj,
221 &stream_listener, stream);
222 }
223 }
224 }
225
226 static void
get_debug_streams(WaylandContextStruct * wlcontext)227 get_debug_streams(WaylandContextStruct* wlcontext)
228 {
229 char *stream_names;
230 char *stream;
231 const char separator[2] = " ";
232
233 stream_names = getenv("IVI_CLIENT_DEBUG_STREAM_NAMES");
234
235 if(NULL == stream_names)
236 return;
237
238 /* get the first stream */
239 stream = strtok(stream_names, separator);
240
241 /* walk through other streams */
242 while( stream != NULL ) {
243 stream_alloc(wlcontext, stream);
244 stream = strtok(NULL, separator);
245 }
246 }
247 #endif
248
249 static void
shm_format(void * data,struct wl_shm * wl_shm,uint32_t format)250 shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
251 {
252 WaylandContextStruct* wlcontext = data;
253
254 wlcontext->formats |= (1 << format);
255 }
256
257 static struct wl_shm_listener shm_listenter = {
258 shm_format
259 };
260
create_cursors(WaylandContextStruct * wlcontext)261 static int create_cursors(WaylandContextStruct* wlcontext) {
262 int size = 32;
263 unsigned int j;
264
265 wlcontext->cursor_theme = wl_cursor_theme_load(NULL, size, wlcontext->wl_shm);
266 if (!wlcontext->cursor_theme) {
267 fprintf(stderr, "could not load default theme\n");
268 return -1;
269 }
270
271 wlcontext->cursor = NULL;
272
273 for (j = 0; !wlcontext->cursor && j < 4; ++j)
274 wlcontext->cursor = wl_cursor_theme_get_cursor(wlcontext->cursor_theme, left_ptrs[j]);
275
276 if (!wlcontext->cursor)
277 {
278 fprintf(stderr, "could not load cursor '%s'\n", left_ptrs[j]);
279 return -1;
280 }
281
282 return 0;
283 }
284
set_pointer_image(WaylandContextStruct * wlcontext)285 static int set_pointer_image(WaylandContextStruct* wlcontext)
286 {
287 struct wl_cursor *cursor = NULL;
288 struct wl_cursor_image *image = NULL;
289 struct wl_buffer *buffer = NULL;
290
291 if (!wlcontext->wl_pointer || !wlcontext->cursor) {
292 fprintf(stderr, "no wl_pointer or no wl_cursor\n");
293 return -1;
294 }
295
296 cursor = wlcontext->cursor;
297 image = cursor->images[0];
298 buffer = wl_cursor_image_get_buffer(image);
299 if (!buffer) {
300 fprintf(stderr, "buffer for cursor not available\n");
301 return -1;
302 }
303
304 wl_pointer_set_cursor(wlcontext->wl_pointer, 0,
305 wlcontext->wl_pointer_surface,
306 image->hotspot_x, image->hotspot_y);
307 wl_surface_attach(wlcontext->wl_pointer_surface, buffer, 0, 0);
308 wl_surface_damage(wlcontext->wl_pointer_surface, 0, 0,
309 image->width, image->height);
310 wl_surface_commit(wlcontext->wl_pointer_surface);
311
312 return 0;
313 }
314
315 static void
PointerHandleEnter(void * data,struct wl_pointer * wlPointer,uint32_t serial,struct wl_surface * wlSurface,wl_fixed_t sx,wl_fixed_t sy)316 PointerHandleEnter(void *data, struct wl_pointer *wlPointer, uint32_t serial,
317 struct wl_surface *wlSurface, wl_fixed_t sx, wl_fixed_t sy)
318 {
319 WaylandContextStruct *wlcontext = (WaylandContextStruct*)data;
320
321 set_pointer_image(wlcontext);
322
323 printf("ENTER EGLWLINPUT PointerHandleEnter: x(%d), y(%d)\n",
324 wl_fixed_to_int(sx), wl_fixed_to_int(sy));
325 }
326
327 static void
PointerHandleLeave(void * data,struct wl_pointer * wlPointer,uint32_t serial,struct wl_surface * wlSurface)328 PointerHandleLeave(void *data, struct wl_pointer *wlPointer, uint32_t serial,
329 struct wl_surface *wlSurface)
330 {
331
332 }
333
334 static void
PointerHandleMotion(void * data,struct wl_pointer * wlPointer,uint32_t time,wl_fixed_t sx,wl_fixed_t sy)335 PointerHandleMotion(void *data, struct wl_pointer *wlPointer, uint32_t time,
336 wl_fixed_t sx, wl_fixed_t sy)
337 {
338
339 }
340
341 static void
PointerHandleAxis(void * data,struct wl_pointer * wlPointer,uint32_t time,uint32_t axis,wl_fixed_t value)342 PointerHandleAxis(void *data, struct wl_pointer *wlPointer, uint32_t time,
343 uint32_t axis, wl_fixed_t value)
344 {
345
346 }
347
348 static void
PointerHandleButton(void * data,struct wl_pointer * wlPointer,uint32_t serial,uint32_t time,uint32_t button,uint32_t state)349 PointerHandleButton(void *data, struct wl_pointer *wlPointer, uint32_t serial,
350 uint32_t time, uint32_t button, uint32_t state)
351 {
352
353 }
354
355 static void
PointerHandleFrame(void * data,struct wl_pointer * wl_pointer)356 PointerHandleFrame(void *data, struct wl_pointer *wl_pointer)
357 {
358
359 }
360
361 static void
PointerHandleAxisSource(void * data,struct wl_pointer * wl_pointer,uint32_t axis_source)362 PointerHandleAxisSource(void *data, struct wl_pointer *wl_pointer,
363 uint32_t axis_source)
364 {
365
366 }
367
368 static void
PointerHandleAxisStop(void * data,struct wl_pointer * wl_pointer,uint32_t time,uint32_t axis)369 PointerHandleAxisStop(void *data, struct wl_pointer *wl_pointer,
370 uint32_t time, uint32_t axis)
371 {
372
373 }
374
375 static void
PointerHandleAxisDiscrete(void * data,struct wl_pointer * wl_pointer,uint32_t axis,int32_t discrete)376 PointerHandleAxisDiscrete(void *data, struct wl_pointer *wl_pointer,
377 uint32_t axis, int32_t discrete)
378 {
379
380 }
381
382 static struct wl_pointer_listener pointer_listener = {
383 PointerHandleEnter,
384 PointerHandleLeave,
385 PointerHandleMotion,
386 PointerHandleButton,
387 PointerHandleAxis,
388 PointerHandleFrame,
389 PointerHandleAxisSource,
390 PointerHandleAxisStop,
391 PointerHandleAxisDiscrete
392 };
393
394 static void
seat_handle_capabilities(void * data,struct wl_seat * seat,uint32_t caps)395 seat_handle_capabilities(void *data, struct wl_seat *seat, uint32_t caps)
396 {
397 WaylandContextStruct *wlcontext = (WaylandContextStruct*)data;
398 struct wl_seat *wl_seat = wlcontext->wl_seat;
399
400 if ((caps & WL_SEAT_CAPABILITY_POINTER) && !wlcontext->wl_pointer) {
401 wlcontext->wl_pointer = wl_seat_get_pointer(wl_seat);
402 wl_pointer_add_listener(wlcontext->wl_pointer,
403 &pointer_listener, data);
404 /*create cursors*/
405 create_cursors(wlcontext);
406 wlcontext->wl_pointer_surface =
407 wl_compositor_create_surface(wlcontext->wl_compositor);
408 } else
409 if (!(caps & WL_SEAT_CAPABILITY_POINTER) && wlcontext->wl_pointer) {
410 wl_pointer_destroy(wlcontext->wl_pointer);
411 wlcontext->wl_pointer = NULL;
412
413 if (wlcontext->wl_pointer_surface) {
414 wl_surface_destroy(wlcontext->wl_pointer_surface);
415 wlcontext->wl_pointer_surface = NULL;
416 }
417
418 if (wlcontext->cursor_theme)
419 wl_cursor_theme_destroy(wlcontext->cursor_theme);
420 }
421 }
422
423 static void
seat_name(void * data,struct wl_seat * wl_seat,const char * name)424 seat_name(void *data, struct wl_seat *wl_seat, const char *name)
425 {
426
427 }
428
429 static struct wl_seat_listener seat_Listener = {
430 seat_handle_capabilities,
431 seat_name
432 };
433
434 #ifdef LIBWESTON_DEBUG_PROTOCOL
435 static void
stream_find(WaylandContextStruct * wlcontext,const char * name,const char * desc)436 stream_find(WaylandContextStruct* wlcontext, const char *name, const char *desc)
437 {
438 struct debug_stream *stream;
439 wl_list_for_each(stream, &wlcontext->stream_list, link)
440 if (strcmp(stream->name, name) == 0) {
441 stream->should_bind = 1;
442 }
443 }
444
445 static void
debug_advertise(void * data,struct weston_debug_v1 * debug,const char * name,const char * desc)446 debug_advertise(void *data, struct weston_debug_v1 *debug, const char *name,
447 const char *desc)
448 {
449 WaylandContextStruct* wlcontext = data;
450 stream_find(wlcontext, name, desc);
451 }
452
453 static const struct weston_debug_v1_listener debug_listener = {
454 debug_advertise
455 };
456 #endif
457
458 static void
registry_handle_global(void * data,struct wl_registry * registry,uint32_t name,const char * interface,uint32_t version)459 registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
460 const char *interface, uint32_t version)
461 {
462 WaylandContextStruct* wlcontext = (WaylandContextStruct*)data;
463
464 if (!strcmp(interface, "wl_compositor")) {
465 wlcontext->wl_compositor =
466 wl_registry_bind(registry, name,
467 &wl_compositor_interface, 1);
468 }
469 else if (!strcmp(interface, "wl_shm")) {
470 wlcontext->wl_shm =
471 wl_registry_bind(registry, name, &wl_shm_interface, 1);
472 wl_shm_add_listener(wlcontext->wl_shm, &shm_listenter, wlcontext);
473 }
474 else if (!strcmp(interface, "ivi_application")) {
475 wlcontext->ivi_application =
476 wl_registry_bind(registry, name,
477 &ivi_application_interface, 1);
478 }
479 else if (!strcmp(interface, "wl_seat")) {
480 if (wlcontext->enable_cursor) {
481 wlcontext->wl_seat =
482 wl_registry_bind(registry, name, &wl_seat_interface, 1);
483 wl_seat_add_listener(wlcontext->wl_seat, &seat_Listener, data);
484 }
485 }
486 #ifdef LIBWESTON_DEBUG_PROTOCOL
487 else if (!strcmp(interface, weston_debug_v1_interface.name)) {
488 uint32_t myver;
489
490 if (wlcontext->debug_iface || wl_list_empty(&wlcontext->stream_list))
491 return;
492
493 myver = MIN(1, version);
494 wlcontext->debug_iface =
495 wl_registry_bind(registry, name,
496 &weston_debug_v1_interface, myver);
497 weston_debug_v1_add_listener(wlcontext->debug_iface, &debug_listener,
498 wlcontext);
499 }
500 #endif
501 }
502
503 static void
registry_handle_global_remove(void * data,struct wl_registry * registry,uint32_t name)504 registry_handle_global_remove(void *data, struct wl_registry *registry,
505 uint32_t name)
506 {
507
508 }
509
510 static const struct wl_registry_listener registry_listener = {
511 registry_handle_global,
512 registry_handle_global_remove
513 };
514
init_wayland_context(WaylandContextStruct * wlcontext)515 int init_wayland_context(WaylandContextStruct* wlcontext)
516 {
517 wlcontext->wl_display = wl_display_connect(NULL);
518 if (NULL == wlcontext->wl_display) {
519 printf("Error: wl_display_connect failed\n");
520 return -1;
521 }
522
523 wlcontext->wl_registry = wl_display_get_registry(wlcontext->wl_display);
524 wl_registry_add_listener(wlcontext->wl_registry,
525 ®istry_listener, wlcontext);
526 wl_display_roundtrip(wlcontext->wl_display);
527
528 if (wlcontext->wl_shm == NULL) {
529 fprintf(stderr, "No wl_shm global\n");
530 return -1;
531 }
532
533 wl_display_roundtrip(wlcontext->wl_display);
534
535 if (!(wlcontext->formats & (1 << WL_SHM_FORMAT_XRGB8888))) {
536 fprintf(stderr, "WL_SHM_FORMAT_XRGB32 not available\n");
537 return -1;
538 }
539
540 #ifdef LIBWESTON_DEBUG_PROTOCOL
541 if (!wl_list_empty(&wlcontext->stream_list) &&
542 (wlcontext->debug_iface == NULL)) {
543 fprintf(stderr, "WARNING: weston_debug protocol is not available,"
544 " missed enabling --debug option to weston ?\n");
545 }
546 #endif
547
548 return 0;
549 }
550
destroy_wayland_context(WaylandContextStruct * wlcontext)551 void destroy_wayland_context(WaylandContextStruct* wlcontext)
552 {
553 if(wlcontext->wl_compositor)
554 wl_compositor_destroy(wlcontext->wl_compositor);
555
556 if(wlcontext->wl_display)
557 wl_display_disconnect(wlcontext->wl_display);
558 }
559
560 int
create_file(int size)561 create_file(int size)
562 {
563 static const char template[] = "/weston-shared-XXXXXX";
564 const char *path;
565 char *name;
566 int fd;
567 int ret;
568 long flags;
569
570 path = getenv("XDG_RUNTIME_DIR");
571 if (!path) {
572 errno = ENOENT;
573 return -1;
574 }
575
576 name = malloc(strlen(path) + sizeof(template));
577 if (!name)
578 return -1;
579
580 strcpy(name, path);
581 strcat(name, template);
582
583 fd = mkstemp(name);
584 if (fd >= 0) {
585 flags = fcntl(fd, F_GETFD);
586 fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
587 unlink(name);
588 }
589
590 free(name);
591
592 if (fd < 0)
593 return -1;
594
595 ret = ftruncate(fd, size);
596 if (ret < 0) {
597 close(fd);
598 return -1;
599 }
600
601 return fd;
602 }
603
604 static int
create_shm_buffer(WaylandContextStruct * wlcontext)605 create_shm_buffer(WaylandContextStruct* wlcontext)
606 {
607 struct wl_shm_pool *pool;
608 BkGndSettingsStruct* bkgnd_settings = wlcontext->bkgnd_settings;
609
610 int fd = -1;
611 int size = 0;
612 int stride = 0;
613
614 stride = bkgnd_settings->surface_stride;
615 size = stride * bkgnd_settings->surface_height;
616 fd = create_file(size);
617 if (fd < 0) {
618 fprintf(stderr, "creating a buffer file for %d B failed: %m\n",
619 size);
620 return -1;
621 }
622
623 wlcontext->bkgnddata =
624 mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
625
626 if (MAP_FAILED == wlcontext->bkgnddata) {
627 fprintf(stderr, "mmap failed: %m\n");
628 close(fd);
629 return -1;
630 }
631
632 pool = wl_shm_create_pool(wlcontext->wl_shm, fd, size);
633 wlcontext->wlBkgndBuffer = wl_shm_pool_create_buffer(pool,
634 0,
635 bkgnd_settings->surface_width,
636 bkgnd_settings->surface_height,
637 stride,
638 WL_SHM_FORMAT_ARGB8888);
639 if (NULL == wlcontext->wlBkgndBuffer) {
640 fprintf(stderr, "wl_shm_create_buffer failed: %m\n");
641 close(fd);
642 return -1;
643 }
644
645 wl_shm_pool_destroy(pool);
646 close(fd);
647
648 return 0;
649 }
650
draw_bkgnd_surface(WaylandContextStruct * wlcontext)651 int draw_bkgnd_surface(WaylandContextStruct* wlcontext)
652 {
653 BkGndSettingsStruct *bkgnd_settings = wlcontext->bkgnd_settings;
654 uint32_t* pixels;
655
656 pixels = (uint32_t*)wlcontext->bkgnddata;
657 *pixels = 0x0;
658
659 wl_surface_attach(wlcontext->wlBkgndSurface, wlcontext->wlBkgndBuffer, 0, 0);
660 wl_surface_damage(wlcontext->wlBkgndSurface, 0, 0,
661 bkgnd_settings->surface_width, bkgnd_settings->surface_height);
662 wl_surface_commit(wlcontext->wlBkgndSurface);
663
664 return 0;
665 }
666
create_bkgnd_surface(WaylandContextStruct * wlcontext)667 int create_bkgnd_surface(WaylandContextStruct* wlcontext)
668 {
669 BkGndSettingsStruct *bkgnd_settings = wlcontext->bkgnd_settings;
670
671 wlcontext->wlBkgndSurface =
672 wl_compositor_create_surface(wlcontext->wl_compositor);
673 if (NULL == wlcontext->wlBkgndSurface) {
674 printf("Error: wl_compositor_create_surface failed.\n");
675 return -1;
676 }
677
678 if (create_shm_buffer(wlcontext)) {
679 printf("Error: shm buffer creation failed.\n");
680 return -1;
681 }
682
683 wlcontext->ivi_surf = ivi_application_surface_create(wlcontext->ivi_application,
684 bkgnd_settings->surface_id,
685 wlcontext->wlBkgndSurface);
686
687 return 0;
688 }
689
destroy_bkgnd_surface(WaylandContextStruct * wlcontext)690 void destroy_bkgnd_surface(WaylandContextStruct* wlcontext)
691 {
692 if (wlcontext->ivi_surf)
693 ivi_surface_destroy(wlcontext->ivi_surf);
694
695 if (wlcontext->wlBkgndSurface)
696 wl_surface_destroy(wlcontext->wlBkgndSurface);
697 }
698
699 #ifdef LIBWESTON_DEBUG_PROTOCOL
700 static void *
weston_dlt_thread_function(void * data)701 weston_dlt_thread_function(void *data)
702 {
703 WaylandContextStruct* wlcontext;
704 char apid[DLT_ID_SIZE];
705 char ctid[DLT_ID_SIZE];
706 DLT_DECLARE_CONTEXT(weston_dlt_context)
707
708 wlcontext = (WaylandContextStruct*)data;
709
710 /*init dlt*/
711 dlt_set_id(apid, WESTON_DLT_APP);
712 dlt_set_id(ctid, WESTON_DLT_CONTEXT);
713
714 DLT_REGISTER_APP(apid, WESTON_DLT_APP_DESC);
715 DLT_REGISTER_CONTEXT(weston_dlt_context, ctid, WESTON_DLT_CONTEXT_DESC);
716
717 /*make the stdin as read end of the pipe*/
718 dup2(wlcontext->pipefd[0], STDIN_FILENO);
719
720 while (running && wlcontext->thread_running)
721 {
722 char str[MAXSTRLEN] = {0};
723 int i = -1;
724
725 /* read from std-in(read end of pipe) till newline char*/
726 do {
727 i++;
728 if (read(wlcontext->pipefd[0], &str[i], 1) < 0)
729 printf("read failed : %s", strerror(errno));
730 } while (str[i] != '\n');
731
732 if (strcmp(str,"")!=0)
733 {
734 DLT_LOG(weston_dlt_context, DLT_LOG_INFO, DLT_STRING(str));
735 }
736 }
737
738 DLT_UNREGISTER_CONTEXT(weston_dlt_context);
739 DLT_UNREGISTER_APP();
740 pthread_exit(NULL);
741 }
742 #endif
743
744 static void
signal_int(int signum)745 signal_int(int signum)
746 {
747 running = 0;
748 }
749
750 static int
display_poll(struct wl_display * display,short int events)751 display_poll(struct wl_display *display, short int events)
752 {
753 int ret;
754 struct pollfd pfd[1];
755
756 pfd[0].fd = wl_display_get_fd(display);
757 pfd[0].events = events;
758 do {
759 ret = poll(pfd, 1, -1);
760 } while (ret == -1 && errno == EINTR && running);
761
762 if(0 == running)
763 ret = -1;
764
765 return ret;
766 }
767
768 /* implemented local API for dispatch the default queue
769 * to handle the Ctrl+C signal properly, with the wl_display_dispatch
770 * the poll is continuing because the generated errno is EINTR,
771 * so added running flag also to decide whether to continue polling or not */
772 static int
display_dispatch(struct wl_display * display)773 display_dispatch(struct wl_display *display)
774 {
775 int ret;
776
777 if (wl_display_prepare_read(display) == -1)
778 return wl_display_dispatch_pending(display);
779
780 while (1) {
781 ret = wl_display_flush(display);
782
783 if (ret != -1 || errno != EAGAIN)
784 break;
785
786 if (display_poll(display, POLLOUT) == -1) {
787 wl_display_cancel_read(display);
788 return -1;
789 }
790 }
791
792 /* Don't stop if flushing hits an EPIPE; continue so we can read any
793 * protocol error that may have triggered it. */
794 if (ret < 0 && errno != EPIPE) {
795 wl_display_cancel_read(display);
796 return -1;
797 }
798
799 if (display_poll(display, POLLIN) == -1) {
800 wl_display_cancel_read(display);
801 return -1;
802 }
803
804 if (wl_display_read_events(display) == -1)
805 return -1;
806
807 return wl_display_dispatch_pending(display);
808 }
809
main(int argc,const char * argv[])810 int main (int argc, const char * argv[])
811 {
812 WaylandContextStruct* wlcontext;
813 BkGndSettingsStruct* bkgnd_settings;
814
815 struct sigaction sigint;
816 int ret = 0;
817
818 sigint.sa_handler = signal_int;
819 sigemptyset(&sigint.sa_mask);
820 sigaction(SIGINT, &sigint, NULL);
821 sigaction(SIGTERM, &sigint, NULL);
822 sigaction(SIGSEGV, &sigint, NULL);
823
824 wlcontext = (WaylandContextStruct*)calloc(1, sizeof(WaylandContextStruct));
825
826 /*get bkgnd settings and create shm-surface*/
827 bkgnd_settings = get_bkgnd_settings_cursor_info(wlcontext);
828
829 /*init wayland context*/
830 wlcontext->bkgnd_settings = bkgnd_settings;
831
832 #ifdef LIBWESTON_DEBUG_PROTOCOL
833 /*init debug stream list*/
834 wl_list_init(&wlcontext->stream_list);
835 get_debug_streams(wlcontext);
836 wlcontext->debug_fd = STDOUT_FILENO;
837 #else
838 fprintf(stderr, "WARNING: weston_debug protocol is not available\n");
839 #endif
840
841 if (init_wayland_context(wlcontext)) {
842 fprintf(stderr, "init_wayland_context failed\n");
843 goto ErrorContext;
844 }
845
846 if (create_bkgnd_surface(wlcontext)) {
847 fprintf(stderr, "create_bkgnd_surface failed\n");
848 goto Error;
849 }
850
851 wl_display_roundtrip(wlcontext->wl_display);
852
853 #ifdef LIBWESTON_DEBUG_PROTOCOL
854 if (!wl_list_empty(&wlcontext->stream_list) &&
855 wlcontext->debug_iface) {
856 /* create the pipe b/w stdout and stdin
857 * stdout - write end
858 * stdin - read end
859 * weston will write to stdout and the
860 * dlt_ctx_thread will read from stdin */
861 if ((pipe(wlcontext->pipefd)) < 0)
862 printf("Error in pipe() processing : %s", strerror(errno));
863
864 dup2(wlcontext->pipefd[1], STDOUT_FILENO);
865
866 wlcontext->thread_running = 1;
867 pthread_create(&wlcontext->dlt_ctx_thread, NULL,
868 weston_dlt_thread_function, wlcontext);
869 start_streams(wlcontext);
870 }
871 #endif
872
873 /*draw the bkgnd display*/
874 draw_bkgnd_surface(wlcontext);
875
876 while (running && (ret != -1)) {
877 ret = display_dispatch(wlcontext->wl_display);
878 }
879
880 Error:
881 #ifdef LIBWESTON_DEBUG_PROTOCOL
882 weston_debug_v1_destroy(wlcontext->debug_iface);
883
884 while (1) {
885 struct debug_stream *stream;
886 int empty = 1;
887
888 wl_list_for_each(stream, &wlcontext->stream_list, link)
889 if (stream->obj) {
890 empty = 0;
891 break;
892 }
893
894 if (empty)
895 break;
896
897 if (wl_display_dispatch(wlcontext->wl_display) < 0)
898 break;
899 }
900
901 destroy_streams(wlcontext);
902 wl_display_roundtrip(wlcontext->wl_display);
903
904 if(wlcontext->thread_running)
905 {
906 close(wlcontext->pipefd[1]);
907 close(STDOUT_FILENO);
908 wlcontext->thread_running = 0;
909 pthread_join(wlcontext->dlt_ctx_thread, NULL);
910 close(wlcontext->pipefd[0]);
911 }
912 #endif
913
914 destroy_bkgnd_surface(wlcontext);
915 ErrorContext:
916 destroy_wayland_context(wlcontext);
917
918 free(bkgnd_settings);
919 free(wlcontext);
920
921 return 0;
922 }
923