822590c75c0fcfb10f446d883dfd5b44a6ed6a5e
[src/libhomescreen.git] / sample / simple-egl / src / simple-egl.cpp
1 /*
2  * Copyright (c) 2017 TOYOTA MOTOR CORPORATION
3  * Copyright © 2011 Benjamin Franzke
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24
25 #include <mutex>
26 #include <chrono>
27
28 #include <iostream>
29 #include <string>
30 #include <stdarg.h>
31 #include <sys/types.h>
32 #include <thread>
33 #include <exception>
34 #include <vector>
35 #include <sstream>
36
37 #include <assert.h>
38 #include <signal.h>
39
40 #include <wayland-client.h>
41 #include <wayland-egl.h>
42
43 #include <GLES2/gl2.h>
44 #include <EGL/egl.h>
45 #include <EGL/eglext.h>
46
47 #include <unistd.h>
48 #include <time.h>
49
50 #include "libwindowmanager.h"
51 #include <libhomescreen.hpp>
52
53 #include <ilm/ivi-application-client-protocol.h>
54 using namespace std;
55
56
57 uint32_t g_id_ivisurf = 9009;
58 long port = 1700;
59 string token = string("wm");
60 bool enable_debug = false;
61
62 string app_name = string("Navigation");
63
64 LibHomeScreen* hs;
65 LibWindowmanager *wm;
66 bool gIsDraw = false;
67
68 static const struct wl_interface *types[] = {
69         NULL,
70         NULL,
71         NULL,
72         &wl_surface_interface,
73         &ivi_surface_interface,
74 };
75
76 static const struct wl_message ivi_surface_requests[] = {
77         { "destroy", "", types + 0 },
78 };
79
80 static const struct wl_message ivi_surface_events[] = {
81         { "configure", "ii", types + 0 },
82 };
83
84 const struct wl_interface ivi_surface_interface = {
85         "ivi_surface", 1,
86         1, ivi_surface_requests,
87         1, ivi_surface_events,
88 };
89
90 static const struct wl_message ivi_application_requests[] = {
91         { "surface_create", "uon", types + 2 },
92 };
93
94 const struct wl_interface ivi_application_interface = {
95         "ivi_application", 1,
96         1, ivi_application_requests,
97         0, NULL,
98 };
99
100 #include "platform.h"
101
102 #ifndef EGL_EXT_swap_buffers_with_damage
103 #define EGL_EXT_swap_buffers_with_damage 1
104 typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC)(EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
105 #endif
106
107 #ifndef EGL_EXT_buffer_age
108 #define EGL_EXT_buffer_age 1
109 #define EGL_BUFFER_AGE_EXT                      0x313D
110 #endif
111
112 struct window;
113 struct seat;
114
115 struct display {
116         struct wl_display *display;
117         struct wl_registry *registry;
118         struct wl_compositor *compositor;
119         struct wl_seat *seat;
120         struct {
121                 EGLDisplay dpy;
122                 EGLContext ctx;
123                 EGLConfig conf;
124         } egl;
125         struct window *window;
126         struct ivi_application *ivi_application;
127
128         PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC swap_buffers_with_damage;
129 };
130
131 struct geometry {
132         int width, height;
133 };
134
135 struct window {
136         struct display *display;
137         struct geometry geometry, window_size;
138         struct {
139                 GLuint rotation_uniform;
140                 GLuint pos;
141                 GLuint col;
142         } gl;
143
144         uint32_t benchmark_time, frames;
145         struct wl_egl_window *native;
146         struct wl_surface *surface;
147         struct ivi_surface *ivi_surface;
148         EGLSurface egl_surface;
149         struct wl_callback *callback;
150         int fullscreen, opaque, buffer_size, frame_sync;
151 } *gWindow;
152
153 static const char *vert_shader_text =
154         "uniform mat4 rotation;\n"
155         "attribute vec4 pos;\n"
156         "attribute vec4 color;\n"
157         "varying vec4 v_color;\n"
158         "void main() {\n"
159         "  gl_Position = rotation * pos;\n"
160         "  v_color = color;\n"
161         "}\n";
162
163 static const char *frag_shader_text =
164         "precision mediump float;\n"
165         "varying vec4 v_color;\n"
166         "void main() {\n"
167         "  gl_FragColor = v_color;\n"
168         "}\n";
169
170 static int running = 1;
171
172 static void debug_out(const char* str, ...)
173 {
174         if(!enable_debug)
175                 return;
176         char *out;
177         va_list arg_ptr;
178         va_start(arg_ptr, str);
179         vasprintf(&out, str, arg_ptr);
180         cout << out;
181         va_end(arg_ptr);
182         // cout << endl;
183 }
184
185 static void
186 init_egl(struct display *display, struct window *window)
187 {
188         static const EGLint context_attribs[] = {
189                 EGL_CONTEXT_CLIENT_VERSION, 2,
190                 EGL_NONE
191         };
192         const char *extensions;
193
194         EGLint config_attribs[] = {
195                 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
196                 EGL_RED_SIZE, 1,
197                 EGL_GREEN_SIZE, 1,
198                 EGL_BLUE_SIZE, 1,
199                 EGL_ALPHA_SIZE, 1,
200                 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
201                 EGL_NONE
202         };
203
204         EGLint major, minor, n, count, i, size;
205         EGLConfig *configs;
206         EGLBoolean ret;
207
208         if (window->opaque || window->buffer_size == 16)
209                 config_attribs[9] = 0;
210         
211         display->egl.dpy = weston_platform_get_egl_display(EGL_PLATFORM_WAYLAND_KHR, display->display, NULL);
212         assert(display->egl.dpy);
213
214         ret = eglInitialize(display->egl.dpy, &major, &minor);
215         assert(ret == EGL_TRUE);
216         ret = eglBindAPI(EGL_OPENGL_ES_API);
217         assert(ret == EGL_TRUE);
218
219         if (!eglGetConfigs(display->egl.dpy, NULL, 0, &count) || count < 1)
220                 assert(0);
221
222         configs = calloc(count, sizeof *configs);
223         assert(configs);
224
225         ret = eglChooseConfig(display->egl.dpy, config_attribs,
226                               configs, count, &n);
227         assert(ret && n >= 1);
228
229         for (i = 0; i < n; i++) {
230                 eglGetConfigAttrib(display->egl.dpy,
231                                    configs[i], EGL_BUFFER_SIZE, &size);
232                 if (window->buffer_size == size) {
233                         display->egl.conf = configs[i];
234                         break;
235                 }
236         }
237         free(configs);
238         if (display->egl.conf == NULL) {
239                 debug_out("did not find config with buffer size %d\n",
240                         window->buffer_size);
241                 exit(EXIT_FAILURE);
242         }
243
244         display->egl.ctx = eglCreateContext(display->egl.dpy,
245                                             display->egl.conf,
246                                             EGL_NO_CONTEXT, context_attribs);
247         assert(display->egl.ctx);
248
249         display->swap_buffers_with_damage = NULL;
250         extensions = eglQueryString(display->egl.dpy, EGL_EXTENSIONS);
251         if (extensions &&
252             strstr(extensions, "EGL_EXT_swap_buffers_with_damage") &&
253             strstr(extensions, "EGL_EXT_buffer_age"))
254                 display->swap_buffers_with_damage =
255                         (PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC)
256                         eglGetProcAddress("eglSwapBuffersWithDamageEXT");
257
258         if (display->swap_buffers_with_damage)
259                 debug_out("has EGL_EXT_buffer_age and EGL_EXT_swap_buffers_with_damage\n");
260
261 }
262
263 static void
264 fini_egl(struct display *display)
265 {
266         eglTerminate(display->egl.dpy);
267         eglReleaseThread();
268 }
269
270 static GLuint
271 create_shader(struct window *window, const char *source, GLenum shader_type)
272 {
273         GLuint shader;
274         GLint status;
275
276         shader = glCreateShader(shader_type);
277         assert(shader != 0);
278
279         glShaderSource(shader, 1, (const char **) &source, NULL);
280         glCompileShader(shader);
281
282         glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
283         if (!status) {
284                 char log[1000];
285                 GLsizei len;
286                 glGetShaderInfoLog(shader, 1000, &len, log);
287                 debug_out("Error: compiling %s: %*s\n",
288                         shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment",
289                         len, log);
290                 exit(1);
291         }
292
293         return shader;
294 }
295
296 static void
297 init_gl(struct window *window)
298 {
299         GLuint frag, vert;
300         GLuint program;
301         GLint status;
302
303         frag = create_shader(window, frag_shader_text, GL_FRAGMENT_SHADER);
304         vert = create_shader(window, vert_shader_text, GL_VERTEX_SHADER);
305
306         program = glCreateProgram();
307         glAttachShader(program, frag);
308         glAttachShader(program, vert);
309         glLinkProgram(program);
310
311         glGetProgramiv(program, GL_LINK_STATUS, &status);
312         if (!status) {
313                 char log[1000];
314                 GLsizei len;
315                 glGetProgramInfoLog(program, 1000, &len, log);
316                 debug_out("Error: linking:\n%*s\n", len, log);
317                 exit(1);
318         }
319
320         glUseProgram(program);
321
322         window->gl.pos = 0;
323         window->gl.col = 1;
324
325         glBindAttribLocation(program, window->gl.pos, "pos");
326         glBindAttribLocation(program, window->gl.col, "color");
327         glLinkProgram(program);
328
329         window->gl.rotation_uniform =
330                 glGetUniformLocation(program, "rotation");
331 }
332
333 static void
334 create_ivi_surface(struct window *window, struct display *display)
335 {
336         uint32_t id_ivisurf = g_id_ivisurf;
337         window->ivi_surface =
338                 ivi_application_surface_create(display->ivi_application,
339                                                id_ivisurf, window->surface);
340
341         if (window->ivi_surface == NULL) {
342                 debug_out("Failed to create ivi_client_surface\n");
343                 abort();
344         }
345
346 }
347
348 static void
349 create_surface(struct window *window)
350 {
351         struct display *display = window->display;
352         EGLBoolean ret;
353
354         window->surface = wl_compositor_create_surface(display->compositor);
355
356         window->native =
357                 wl_egl_window_create(window->surface,
358                                      window->geometry.width,
359                                      window->geometry.height);
360         window->egl_surface =
361                 weston_platform_create_egl_surface(display->egl.dpy,
362                                                    display->egl.conf,
363                                                    window->native, NULL);
364
365
366         if (display->ivi_application ) {
367                 create_ivi_surface(window, display);
368         } else {
369                 assert(0);
370         }
371
372         ret = eglMakeCurrent(window->display->egl.dpy, window->egl_surface,
373                              window->egl_surface, window->display->egl.ctx);
374         assert(ret == EGL_TRUE);
375
376         if (!window->frame_sync)
377                 eglSwapInterval(display->egl.dpy, 0);
378
379 }
380
381 static void
382 destroy_surface(struct window *window)
383 {
384         /* Required, otherwise segfault in egl_dri2.c: dri2_make_current()
385          * on eglReleaseThread(). */
386         eglMakeCurrent(window->display->egl.dpy, EGL_NO_SURFACE, EGL_NO_SURFACE,
387                        EGL_NO_CONTEXT);
388
389         eglDestroySurface(window->display->egl.dpy, window->egl_surface);
390         wl_egl_window_destroy(window->native);
391
392         if (window->display->ivi_application)
393                 ivi_surface_destroy(window->ivi_surface);
394         wl_surface_destroy(window->surface);
395
396         if (window->callback)
397                 wl_callback_destroy(window->callback);
398 }
399
400 static void
401 redraw(void *data, struct wl_callback *callback, uint32_t time)
402 {
403         struct window *window = data;
404         struct display *display = window->display;
405         static const GLfloat verts[3][2] = {
406                 { -0.5, -0.5 },
407                 {  0.5, -0.5 },
408                 {  0,    0.5 }
409         };
410
411         static const GLfloat verts_sub[3][2] = {
412                 { -0.25, -0.5 },
413                 {  0.25, -0.5 },
414                 {  0,    0.5 }
415         };
416
417         static const GLfloat colors_H[3][3] = {
418                 { 1, 1, 1 },
419                 { 1, 1, 1 },
420                 { 1, 1, 1 }
421         };
422
423         static const GLfloat colors_N[3][3] = {
424                 { 1, 0, 0 },
425                 { 0, 1, 0 },
426                 { 0, 0, 1 }
427         };
428
429         GLfloat angle;
430         GLfloat rotation[4][4] = {
431                 { 1, 0, 0, 0 },
432                 { 0, 1, 0, 0 },
433                 { 0, 0, 1, 0 },
434                 { 0, 0, 0, 1 }
435         };
436         static const uint32_t speed_div = 5, benchmark_interval = 5;
437         struct wl_region *region;
438         EGLint rect[4];
439         EGLint buffer_age = 0;
440         struct timeval tv;
441
442         assert(window->callback == callback);
443         window->callback = NULL;
444
445         if (callback)
446                 wl_callback_destroy(callback);
447
448         gettimeofday(&tv, NULL);
449         time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
450         if (window->frames == 0)
451                 window->benchmark_time = time;
452
453         if (time - window->benchmark_time > (benchmark_interval * 1000)) {
454                 debug_out("%d frames in %d seconds: %f fps\n",
455                        window->frames,
456                        benchmark_interval,
457                        (float) window->frames / benchmark_interval);
458                 window->benchmark_time = time;
459                 window->frames = 0;
460         }
461
462         angle = (time / speed_div) % 360 * M_PI / 180.0;
463         rotation[0][0] =  cos(angle);
464         rotation[0][2] =  sin(angle);
465         rotation[2][0] = -sin(angle);
466         rotation[2][2] =  cos(angle);
467
468         if (display->swap_buffers_with_damage)
469                 eglQuerySurface(display->egl.dpy, window->egl_surface,
470                                 EGL_BUFFER_AGE_EXT, &buffer_age);
471
472         glViewport(0, 0, window->geometry.width, window->geometry.height);
473
474         glUniformMatrix4fv(window->gl.rotation_uniform, 1, GL_FALSE,
475                            (GLfloat *) rotation);
476
477         glClearColor(0.0, 0.0, 0.0, 0.5);
478         glClear(GL_COLOR_BUFFER_BIT);
479
480         if(window->geometry.height == 1488)
481         {
482                 glVertexAttribPointer(window->gl.pos, 2, GL_FLOAT, GL_FALSE, 0, verts);
483         }
484         else
485         {
486                 glVertexAttribPointer(window->gl.pos, 2, GL_FLOAT, GL_FALSE, 0, verts_sub);
487         }
488         if(app_name == string("HVAC")){
489                 glVertexAttribPointer(window->gl.col, 3, GL_FLOAT, GL_FALSE, 0, colors_H);
490         }
491         else{
492                 glVertexAttribPointer(window->gl.col, 3, GL_FLOAT, GL_FALSE, 0, colors_N);
493         }
494         glEnableVertexAttribArray(window->gl.pos);
495         glEnableVertexAttribArray(window->gl.col);
496
497         glDrawArrays(GL_TRIANGLES, 0, 3);
498
499         glDisableVertexAttribArray(window->gl.pos);
500         glDisableVertexAttribArray(window->gl.col);
501
502         if (window->opaque || window->fullscreen) {
503                 region = wl_compositor_create_region(window->display->compositor);
504                 wl_region_add(region, 0, 0,
505                               window->geometry.width,
506                               window->geometry.height);
507                 wl_surface_set_opaque_region(window->surface, region);
508                 wl_region_destroy(region);
509         } else {
510                 wl_surface_set_opaque_region(window->surface, NULL);
511         }
512
513         if (display->swap_buffers_with_damage && buffer_age > 0) {
514                 rect[0] = window->geometry.width / 4 - 1;
515                 rect[1] = window->geometry.height / 4 - 1;
516                 rect[2] = window->geometry.width / 2 + 2;
517                 rect[3] = window->geometry.height / 2 + 2;
518                 display->swap_buffers_with_damage(display->egl.dpy,
519                                                   window->egl_surface,
520                                                   rect, 1);
521         } else {
522                 eglSwapBuffers(display->egl.dpy, window->egl_surface);
523         }
524     
525         window->frames++;
526 }
527
528 static void
529 registry_handle_global(void *data, struct wl_registry *registry,
530                        uint32_t name, const char *interface, uint32_t version)
531 {
532         struct display *d = data;
533
534         if (strcmp(interface, "wl_compositor") == 0) {
535                 d->compositor =
536                         wl_registry_bind(registry, name,
537                                          &wl_compositor_interface, 1);
538         } else if (strcmp(interface, "ivi_application") == 0) {
539                 d->ivi_application =
540                         wl_registry_bind(registry, name,
541                                          &ivi_application_interface, 1);
542         }
543 }
544
545 static void
546 registry_handle_global_remove(void *data, struct wl_registry *registry,
547                               uint32_t name)
548 {
549 }
550
551 static const struct wl_registry_listener registry_listener = {
552         registry_handle_global,
553         registry_handle_global_remove
554 };
555
556 static void
557 signal_int(int signum)
558 {
559         running = 0;
560 }
561
562 int
563 init_wm(LibWindowmanager *wm)
564 {
565         char* surfaceIdStr;
566
567         if (wm->init(port, token.c_str()) != 0) {
568                 debug_out("************** [SIMPLE EGL] [WM SIMPLE >>>>] wm init failed. \n");
569                 return -1;
570         }
571
572         json_object *obj = json_object_new_object();
573         json_object_object_add(obj, wm->kKeyDrawingName, json_object_new_string(app_name.c_str()));
574         if (wm->requestSurface(obj) != 0) {
575                 debug_out("************** [SIMPLE EGL] [WM SIMPLE >>>>] wm request surface failed \n");
576                 return -1;
577         }
578
579         wm->set_event_handler(LibWindowmanager::Event_Active, [wm](json_object *object) {
580                 const char *label = json_object_get_string(
581                         json_object_object_get(object, wm->kKeyDrawingName));
582                 debug_out("************** [SIMPLE EGL] [WM SIMPLE >>>>] Surface %s got activated! \n", label);
583         });
584
585         wm->set_event_handler(LibWindowmanager::Event_Inactive, [wm](json_object *object) {
586                 const char *label = json_object_get_string(
587                         json_object_object_get(object, wm->kKeyDrawingName));
588                 debug_out("************** [SIMPLE EGL] [WM SIMPLE >>>>] Surface %s got inactivated!\n", label);
589         });
590
591         wm->set_event_handler(LibWindowmanager::Event_Visible, [wm](json_object *object) {
592                 const char *label = json_object_get_string(
593                         json_object_object_get(object, wm->kKeyDrawingName));
594                 debug_out("************** [SIMPLE EGL] [WM SIMPLE >>>>] Surface %s got visibled!\n", label);
595         });
596
597         wm->set_event_handler(LibWindowmanager::Event_Invisible, [wm](json_object *object) {
598                 const char *label = json_object_get_string(
599                         json_object_object_get(object, wm->kKeyDrawingName));
600                 debug_out("************** [SIMPLE EGL] [WM SIMPLE >>>>] Surface %s got invisibled!\n", label);
601                 gIsDraw = false;
602         });
603
604         wm->set_event_handler(LibWindowmanager::Event_SyncDraw, [wm](json_object *object) {
605                 const char *label = json_object_get_string(
606                         json_object_object_get(object, wm->kKeyDrawingName));
607                 const char *area = json_object_get_string(
608                         json_object_object_get(object, wm->kKeyDrawingArea));
609                 debug_out("************** [SIMPLE EGL] [WM SIMPLE >>>>] Surface %s got syncdraw!\n", label);
610                 if ((wm->kStrLayoutNormal + "." + wm->kStrAreaFull) == std::string(area)) {
611                         wl_egl_window_resize(gWindow->native, 1080, 1488, 0, 0);
612                         gWindow->geometry.width = 1080;
613                         gWindow->geometry.height = 1488;
614                 }
615                 else if ((wm->kStrLayoutSplit + "." + wm->kStrAreaMain) == std::string(area) ||
616                                  (wm->kStrLayoutSplit + "." + wm->kStrAreaSub) == std::string(area)) {
617                         wl_egl_window_resize(gWindow->native, 1080, 744, 0, 0);
618                         gWindow->geometry.width = 1080;
619                         gWindow->geometry.height = 744;
620                 }
621         debug_out("************** [SIMPLE EGL] [WM SIMPLE >>>>] try to endDraw %s \n", app_name.c_str());
622                 if (!gWindow->fullscreen)
623                         gWindow->window_size = gWindow->geometry;
624                 gIsDraw = true;
625                 json_object *obj = json_object_new_object();
626                 json_object_object_add(obj, wm->kKeyDrawingName, json_object_new_string(app_name.c_str()));
627
628         wm->endDraw(obj);
629     });
630
631         wm->set_event_handler(LibWindowmanager::Event_FlushDraw, [wm](json_object *object) {
632                 const char *label = json_object_get_string(
633                         json_object_object_get(object, wm->kKeyDrawingName));
634                 debug_out("************** [SIMPLE EGL] [WM SIMPLE >>>>] Surface %s got flushdraw! \n", label);
635         });
636
637         do
638         {
639         surfaceIdStr = getenv("QT_IVI_SURFACE_ID");
640         } while (surfaceIdStr == NULL);
641
642         g_id_ivisurf = atoi(surfaceIdStr);
643         debug_out("************** [SIMPLE EGL] [WM SIMPLE >>>>] IVI_SURFACE_ID: %d \n", g_id_ivisurf);
644
645         return 0;
646 }
647
648 int
649 init_hs(LibHomeScreen* hs){
650         if(hs->init(port, token)!=0)
651         {
652                 debug_out("************** [SIMPLE EGL] [HS SIMPLE >>>>] homescreen init failed. \n");
653                 return -1;
654         }
655
656         hs->set_event_handler(LibHomeScreen::Event_TapShortcut, [](json_object *object){
657                 const char *application_name = json_object_get_string(
658                         json_object_object_get(object, "application_name"));
659                 debug_out("************** [SIMPLE EGL] [HS SIMPLE >>>>] Event_TapShortcut application_name = %s \n", application_name);
660                 if(strcmp(application_name, app_name.c_str()) == 0)
661                 {
662                         debug_out("************** [SIMPLE EGL] [HS SIMPLE] try to activesurface %s \n", app_name.c_str());
663                         json_object *obj = json_object_new_object();
664                         json_object_object_add(obj, wm->kKeyDrawingName, json_object_new_string(app_name.c_str()));
665                         json_object_object_add(obj, wm->kKeyDrawingArea, json_object_new_string("normal.full"));
666                         gIsDraw = false;
667                         wm->activateSurface(obj);
668                 }
669         });
670
671         hs->set_event_handler(LibHomeScreen::Event_OnScreenMessage, [](json_object *object){
672                 const char *display_message = json_object_get_string(
673                         json_object_object_get(object, "display_message"));
674         debug_out("************** [SIMPLE EGL] [HS SIMPLE >>>>] Event_OnScreenMessage display_message = %s \n", display_message);
675         });
676
677         return 0;
678 }
679
680 int
681 main(int argc, char **argv)
682 {
683         struct sigaction sigint;
684         struct window  window  = { 0 };
685         struct display display = { 0 };
686
687         if(getenv("ENABLE_DEMO_DEBUG"))
688         {
689                 enable_debug = true;
690         }
691
692         window.display = &display;
693         display.window = &window;
694         window.geometry.width  = 1080;
695         window.geometry.height = 1488;
696         window.window_size = window.geometry;
697         window.buffer_size = 32;
698         window.frame_sync = 1;
699         gWindow = &window;
700
701         if(argc > 2)
702         {
703                 if(string(argv[0]).find("hvac") != string::npos)
704                         app_name = string("HVAC");
705                 port = strtol(argv[1], NULL, 10);
706                 token = argv[2];
707         }
708
709         debug_out("************** [SIMPLE EGL] [MAIN] app_name: %s, port: %d, token: %s. \n", app_name.c_str(), port, token.c_str());
710
711         display.display = wl_display_connect(NULL);
712         assert(display.display);
713
714         display.registry = wl_display_get_registry(display.display);
715         wl_registry_add_listener(display.registry,
716                                  &registry_listener, &display);
717
718         wl_display_roundtrip(display.display);
719
720         init_egl(&display, &window);
721
722         wm = new LibWindowmanager();
723         hs = new LibHomeScreen();
724         
725         if(init_wm(wm)!=0){
726                 fini_egl(&display);
727                 if (display.ivi_application)
728                         ivi_application_destroy(display.ivi_application);
729                 if (display.compositor)
730                         wl_compositor_destroy(display.compositor);
731                 wl_registry_destroy(display.registry);
732                 wl_display_flush(display.display);
733                 return -1;
734         }
735
736         if(init_hs(hs)!=0){
737                 fini_egl(&display);
738                 if (display.ivi_application)
739                         ivi_application_destroy(display.ivi_application);
740                 if (display.compositor)
741                         wl_compositor_destroy(display.compositor);
742                 wl_registry_destroy(display.registry);
743                 wl_display_flush(display.display);
744                 return -1;
745         }
746
747         create_surface(&window);
748         init_gl(&window);
749
750         //Ctrl+C
751         sigint.sa_handler = signal_int;
752         sigemptyset(&sigint.sa_mask);
753         sigint.sa_flags = SA_RESETHAND;
754         sigaction(SIGINT, &sigint, NULL);
755
756         wl_display_dispatch_pending(display.display);
757         redraw(&window, NULL, 0);
758         json_object *obj = json_object_new_object();
759         json_object_object_add(obj, wm->kKeyDrawingName, json_object_new_string(app_name.c_str()));
760         json_object_object_add(obj, wm->kKeyDrawingArea, json_object_new_string("normal.full"));
761         wm->activateSurface(obj);
762
763         /* The mainloop here is a little subtle.  Redrawing will cause
764          * EGL to read events so we can just call
765          * wl_display_dispatch_pending() to handle any events that got
766          * queued up as a side effect. */
767         while (running) {
768                 wl_display_dispatch_pending(display.display);
769                 if(!gIsDraw) {
770                         usleep(100000);
771                         continue;
772                 }
773                 else
774                 {
775                         redraw(&window, NULL, 0);
776                 }
777         }
778         debug_out("************** [SIMPLE EGL] [MAIN] simple-egl exiting! \n");
779
780         destroy_surface(&window);
781         fini_egl(&display);
782
783         if (display.ivi_application)
784                 ivi_application_destroy(display.ivi_application);
785
786         if (display.compositor)
787                 wl_compositor_destroy(display.compositor);
788
789         wl_registry_destroy(display.registry);
790         wl_display_flush(display.display);
791         wl_display_disconnect(display.display);
792
793         return 0;
794 }