• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &registry_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