1 /***************************************************************************
2 *
3 * Copyright 2010, 2011 BMW Car IT GmbH
4 * Copyright (C) 2011 DENSO CORPORATION and Robert Bosch Car Multimedia Gmbh
5 *
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 ****************************************************************************/
20 #include "OpenGLES2App.h"
21 #include "LayerScene.h"
22
23 #include <iostream>
24 using std::cout;
25 using std::endl;
26
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <math.h>
30 #include <sys/time.h>
31
32 #include <string.h>
33 #include <stdbool.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <fcntl.h>
37 #include <sys/mman.h>
38 #include <sys/time.h>
39 #include <sys/ioctl.h>
40 #include <sys/types.h>
41
42 #include <stdint.h>
43 #include <signal.h>
44 #include <sys/stat.h>
45 #include <linux/fb.h>
46
47
48 extern "C"
49 {
50 ///////////////////////////////////////////////////////////////////////////////
51 static void
handlePing(void * data,struct wl_shell_surface * shellSurface,uint32_t serial)52 handlePing(void *data, struct wl_shell_surface *shellSurface, uint32_t serial)
53 {
54 (void)data;
55 wl_shell_surface_pong(shellSurface, serial);
56 }
57
58 static void
handleConfigure(void * data,struct wl_shell_surface * shellSurface,uint32_t edges,int32_t width,int32_t height)59 handleConfigure(void *data, struct wl_shell_surface *shellSurface,
60 uint32_t edges, int32_t width, int32_t height)
61 {
62 (void)data;
63 (void)shellSurface;
64 (void)edges;
65 (void)width;
66 (void)height;
67 }
68
69 static void
handlePopupDone(void * data,struct wl_shell_surface * shellSurface)70 handlePopupDone(void *data, struct wl_shell_surface *shellSurface)
71 {
72 (void)data;
73 (void)shellSurface;
74 }
75
76 static const struct wl_shell_surface_listener shellSurfaceListener = {
77 handlePing,
78 handleConfigure,
79 handlePopupDone,
80 };
81
82 ///////////////////////////////////////////////////////////////////////////////
83
registry_handle_global(void * data,struct wl_registry * registry,uint32_t id,const char * interface,uint32_t version)84 void OpenGLES2App::registry_handle_global(void* data, struct wl_registry* registry, uint32_t id, const char* interface, uint32_t version)
85 {
86 WLContextStruct* p_wlCtx = (WLContextStruct*)data;
87 int ans_strcmp = 0;
88 (void)version;
89
90 do
91 {
92 ans_strcmp = strcmp(interface, "wl_compositor");
93 if (0 == ans_strcmp)
94 {
95 p_wlCtx->wlCompositor = (wl_compositor*)wl_registry_bind(registry, id, &wl_compositor_interface, 1);
96 break;
97 }
98
99 ans_strcmp = strcmp(interface, "wl_shell");
100 if (0 == ans_strcmp)
101 {
102 p_wlCtx->wlShell = (struct wl_shell*)wl_registry_bind(registry, id, &wl_shell_interface, 1);
103 break;
104 }
105
106 ans_strcmp = strcmp(interface, "ivi_application");
107 if (0 == ans_strcmp)
108 {
109 p_wlCtx->iviApp = (struct ivi_application*)wl_registry_bind(registry, id, &ivi_application_interface, 1);
110 break;
111 }
112
113 } while(0);
114 }
115
116 static const struct wl_registry_listener registry_listener = {
117 OpenGLES2App::registry_handle_global,
118 NULL
119 };
120 }
121
122 #define RUNTIME_IN_MS() (GetTickCount() - startTimeInMS)
123
124
OpenGLES2App(float fps,float animationSpeed,SurfaceConfiguration * config)125 OpenGLES2App::OpenGLES2App(float fps, float animationSpeed, SurfaceConfiguration* config)
126 : m_framesPerSecond(fps)
127 , m_animationSpeed(animationSpeed)
128 , m_timerIntervalInMs(1000.0 / m_framesPerSecond)
129 , m_surfaceId(0)
130 {
131 createWLContext(config);
132 createEGLContext(config);
133
134 if (config->nosky)
135 {
136 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
137 }
138 else
139 {
140 glClearColor(0.2f, 0.2f, 0.5f, 1.0f);
141 }
142 glDisable(GL_BLEND);
143
144 glClearDepthf(1.0f);
145 glDisable(GL_CULL_FACE);
146 glEnable(GL_DEPTH_TEST);
147 glDepthFunc(GL_LEQUAL);
148 }
149
~OpenGLES2App()150 OpenGLES2App::~OpenGLES2App()
151 {
152 destroyEglContext();
153 destroyWLContext();
154 }
155
mainloop()156 void OpenGLES2App::mainloop()
157 {
158 unsigned int startTimeInMS = GetTickCount();
159 unsigned int frameStartTimeInMS = 0;
160 unsigned int renderTimeInMS = 0;
161 unsigned int frameEndTimeInMS = 0;
162 unsigned int frameTimeInMS = 0;
163
164 while (true)
165 {
166 frameTimeInMS = frameEndTimeInMS - frameStartTimeInMS;
167 frameStartTimeInMS = RUNTIME_IN_MS();
168
169 update(m_animationSpeed * frameStartTimeInMS, m_animationSpeed * frameTimeInMS);
170 render();
171 swapBuffers();
172
173 renderTimeInMS = RUNTIME_IN_MS() - frameStartTimeInMS;
174
175 if (renderTimeInMS < m_timerIntervalInMs)
176 {
177 usleep((m_timerIntervalInMs - renderTimeInMS) * 1000);
178 }
179
180 frameEndTimeInMS = RUNTIME_IN_MS();
181 }
182 }
183
createWLContext(SurfaceConfiguration * config)184 bool OpenGLES2App::createWLContext(SurfaceConfiguration* config)
185 {
186 bool result = true;
187 int width = config->surfaceWidth;
188 int height = config->surfaceHeight;
189
190 memset(&m_wlContextStruct, 0, sizeof(m_wlContextStruct));
191
192 m_wlContextStruct.width = width;
193 m_wlContextStruct.height = height;
194 m_wlContextStruct.wlDisplay = wl_display_connect(NULL);
195 if (NULL == m_wlContextStruct.wlDisplay)
196 {
197 cout<<"Error: wl_display_connect() failed.\n";
198 }
199
200 m_wlContextStruct.wlRegistry = wl_display_get_registry(m_wlContextStruct.wlDisplay);
201 wl_registry_add_listener(m_wlContextStruct.wlRegistry, ®istry_listener, &m_wlContextStruct);
202 wl_display_dispatch(m_wlContextStruct.wlDisplay);
203 wl_display_roundtrip(m_wlContextStruct.wlDisplay);
204
205 m_wlContextStruct.wlSurface = wl_compositor_create_surface(m_wlContextStruct.wlCompositor);
206 if (NULL == m_wlContextStruct.wlSurface)
207 {
208 cout<<"Error: wl_compositor_create_surface() failed.\n";
209 destroyWLContext();
210 }
211
212 if (m_wlContextStruct.iviApp) {
213 m_surfaceId = config->surfaceId;
214 m_wlContextStruct.iviSurface = ivi_application_surface_create(m_wlContextStruct.iviApp,
215 m_surfaceId,
216 m_wlContextStruct.wlSurface);
217 } else if (m_wlContextStruct.wlShell) {
218 m_wlContextStruct.wlShellSurface = wl_shell_get_shell_surface(m_wlContextStruct.wlShell,
219 m_wlContextStruct.wlSurface);
220 }
221
222 if (m_wlContextStruct.wlShellSurface) {
223 wl_shell_surface_add_listener(
224 reinterpret_cast<struct wl_shell_surface*>(m_wlContextStruct.wlShellSurface),
225 &shellSurfaceListener, &m_wlContextStruct);
226 }
227
228 m_wlContextStruct.wlNativeWindow = wl_egl_window_create(m_wlContextStruct.wlSurface, width, height);
229 if (NULL == m_wlContextStruct.wlNativeWindow)
230 {
231 cout<<"Error: wl_egl_window_create() failed"<<endl;
232 destroyWLContext();
233 }
234
235 if (m_wlContextStruct.wlShellSurface) {
236 wl_shell_surface_set_title(m_wlContextStruct.wlShellSurface, "mocknavi");
237 wl_shell_surface_set_toplevel(m_wlContextStruct.wlShellSurface);
238 }
239
240 return result;
241 }
242
createEGLContext(SurfaceConfiguration * config)243 bool OpenGLES2App::createEGLContext(SurfaceConfiguration* config)
244 {
245 bool result = true;
246 EGLint eglstatus = EGL_SUCCESS;
247 m_eglContextStruct.eglDisplay = NULL;
248 m_eglContextStruct.eglSurface = NULL;
249 m_eglContextStruct.eglContext = NULL;
250
251 m_eglContextStruct.eglDisplay = eglGetDisplay(m_wlContextStruct.wlDisplay);
252 if (!m_eglContextStruct.eglDisplay)
253 {
254 cout << "Error: eglGetDisplay() failed.\n";
255 }
256
257 EGLint iMajorVersion, iMinorVersion;
258 if (!eglInitialize(m_eglContextStruct.eglDisplay, &iMajorVersion,
259 &iMinorVersion))
260 {
261 cout << "Error: eglInitialize() failed.\n";
262 }
263
264 eglBindAPI(EGL_OPENGL_ES_API);
265 eglstatus = eglGetError();
266 if (eglstatus != EGL_SUCCESS)
267 {
268 cout << "Error: eglBindAPI() failed.\n";
269 }
270 EGLint pi32ConfigAttribs[] = {
271 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
272 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
273 EGL_RED_SIZE, 8,
274 EGL_GREEN_SIZE, 8,
275 EGL_BLUE_SIZE, 8,
276 EGL_ALPHA_SIZE, 8,
277 EGL_DEPTH_SIZE, 24,
278 EGL_STENCIL_SIZE, 8,
279 EGL_NONE };
280
281 int iConfigs;
282
283 if (!eglChooseConfig(m_eglContextStruct.eglDisplay, pi32ConfigAttribs, &m_eglContextStruct.eglConfig, 1, &iConfigs) || (iConfigs != 1))
284 {
285 cout << "Error: eglChooseConfig() failed.\n";
286 }
287
288 m_eglContextStruct.eglSurface = eglCreateWindowSurface(
289 m_eglContextStruct.eglDisplay, m_eglContextStruct.eglConfig,
290 m_wlContextStruct.wlNativeWindow, NULL);
291 eglstatus = eglGetError();
292
293 if (eglstatus != EGL_SUCCESS)
294 {
295 cout << "Error: eglCreateWindowSurface() failed.\n";
296 }
297
298 EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
299
300 m_eglContextStruct.eglContext = eglCreateContext(
301 m_eglContextStruct.eglDisplay, m_eglContextStruct.eglConfig, NULL,
302 contextAttribs);
303
304 eglstatus = eglGetError();
305 if (eglstatus != EGL_SUCCESS)
306 {
307 cout << "Error: eglCreateContext() failed.\n";
308 }
309
310 eglMakeCurrent(m_eglContextStruct.eglDisplay,
311 m_eglContextStruct.eglSurface, m_eglContextStruct.eglSurface,
312 m_eglContextStruct.eglContext);
313 eglSwapInterval(m_eglContextStruct.eglDisplay, config->sync);
314 eglstatus = eglGetError();
315 if (eglstatus != EGL_SUCCESS)
316 {
317 cout << "Error: eglMakeCurrent() failed.\n";
318 }
319
320 return result;
321 }
322
destroyEglContext()323 void OpenGLES2App::destroyEglContext()
324 {
325 if (m_eglContextStruct.eglDisplay != NULL)
326 {
327 eglMakeCurrent(m_eglContextStruct.eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
328 eglTerminate(m_eglContextStruct.eglDisplay);
329 }
330 }
331
destroyWLContext()332 void OpenGLES2App::destroyWLContext()
333 {
334 if (m_wlContextStruct.wlNativeWindow)
335 {
336 wl_egl_window_destroy(m_wlContextStruct.wlNativeWindow);
337 }
338 if (m_wlContextStruct.iviSurface)
339 {
340 ivi_surface_destroy(m_wlContextStruct.iviSurface);
341 }
342 if (m_wlContextStruct.wlShellSurface)
343 {
344 wl_shell_surface_destroy(reinterpret_cast<struct wl_shell_surface*>(m_wlContextStruct.wlShellSurface));
345 }
346 if (m_wlContextStruct.wlSurface)
347 {
348 wl_surface_destroy(m_wlContextStruct.wlSurface);
349 }
350 if (m_wlContextStruct.wlShell)
351 {
352 wl_shell_destroy(m_wlContextStruct.wlShell);
353 }
354 if (m_wlContextStruct.iviApp)
355 {
356 ivi_application_destroy(m_wlContextStruct.iviApp);
357 }
358 if (m_wlContextStruct.wlCompositor)
359 {
360 wl_compositor_destroy(m_wlContextStruct.wlCompositor);
361 }
362 }
363
GetTickCount()364 unsigned int OpenGLES2App::GetTickCount()
365 {
366 struct timeval ts;
367 gettimeofday(&ts, 0);
368 return (unsigned int) (ts.tv_sec * 1000 + (ts.tv_usec / 1000));
369 }
370
swapBuffers()371 void OpenGLES2App::swapBuffers()
372 {
373 eglSwapBuffers(m_eglContextStruct.eglDisplay, m_eglContextStruct.eglSurface);
374 }
375