5f500b6156527cbfd7166d20af8911cdeaa29fa6
[profile/ivi/layer-management.git] / LayerManagerExamples / EGLWLMockNavigation / src / OpenGLES2App.cpp
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 #include <ilm_client.h>
23
24 #include <iostream>
25 using std::cout;
26 using std::endl;
27
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <math.h>
31 #include <sys/time.h>
32
33 #include <string.h>
34 #include <stdbool.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38 #include <sys/mman.h>
39 #include <sys/time.h>
40 #include <sys/ioctl.h>
41 #include <sys/types.h>
42
43 #include <stdint.h>
44 #include <signal.h>
45 #include <sys/stat.h>
46 #include <linux/fb.h>
47
48 #include "WaylandServerinfoClientProtocol.h"
49
50 extern "C"
51 {
52     void OpenGLES2App::serverinfoListener(void *data, struct serverinfo *pServerinfo, uint32_t client_handle)
53     {
54         pServerinfo = pServerinfo; // TODO:to avoid warning
55         WLContextStruct* p_wlCtx = (WLContextStruct*)data;
56         p_wlCtx->connect_id = client_handle;
57     }
58
59     struct serverinfo_listener serverinfo_listener_list = {
60         OpenGLES2App::serverinfoListener
61     };
62
63     void OpenGLES2App::registry_handle_global(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version)
64     {
65         version = version; // TODO:to avoid warning
66         WLContextStruct* p_wlCtx = (WLContextStruct*)data;
67         int ans_strcmp = 0;
68
69         do
70         {
71             ans_strcmp = strcmp(interface, "wl_compositor");
72             if (0 == ans_strcmp)
73             {
74                 p_wlCtx->wlCompositor = (wl_compositor*)wl_registry_bind(registry, name, &wl_compositor_interface, 1);
75                 break;
76             }
77
78             ans_strcmp = strcmp(interface, "serverinfo");
79             if (0 == ans_strcmp)
80             {
81                 p_wlCtx->wlExtServerinfo = (struct serverinfo*)wl_registry_bind(registry, name, &serverinfo_interface, 1);
82                 serverinfo_add_listener(p_wlCtx->wlExtServerinfo, &serverinfo_listener_list, data);
83                 serverinfo_get_connection_id(p_wlCtx->wlExtServerinfo);
84             }
85         } while(0);
86     }
87
88     static const struct wl_registry_listener registry_listener = {
89         OpenGLES2App::registry_handle_global,
90         NULL
91     };
92 }
93
94 #define RUNTIME_IN_MS() (GetTickCount() - startTimeInMS)
95
96
97 OpenGLES2App::OpenGLES2App(float fps, float animationSpeed, SurfaceConfiguration* config)
98 : m_framesPerSecond(fps)
99 , m_animationSpeed(animationSpeed)
100 , m_timerIntervalInMs(1000.0 / m_framesPerSecond)
101 {
102     ilm_init();
103     createWLContext(config);
104     createEGLContext();
105     setupLayerMangement(config);
106
107     if (config->nosky)
108     {
109         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
110     }
111     else
112     {
113         glClearColor(0.2f, 0.2f, 0.5f, 1.0f);
114     }
115     glDisable(GL_BLEND);
116
117     glClearDepthf(1.0f);
118     glDisable(GL_CULL_FACE);
119     glEnable(GL_DEPTH_TEST);
120     glDepthFunc(GL_LEQUAL);
121 }
122
123 OpenGLES2App::~OpenGLES2App()
124 {
125     destroyEglContext();
126     destroyWLContext();
127     ilm_destroy();
128 }
129
130 void OpenGLES2App::mainloop()
131 {
132     unsigned int startTimeInMS = GetTickCount();
133     unsigned int frameStartTimeInMS = 0;
134     unsigned int renderTimeInMS = 0;
135     unsigned int frameEndTimeInMS = 0;
136     unsigned int frameTimeInMS = 0;
137
138     while (true)
139     {
140         frameTimeInMS = frameEndTimeInMS - frameStartTimeInMS;
141         frameStartTimeInMS = RUNTIME_IN_MS();
142
143         update(m_animationSpeed * frameStartTimeInMS, m_animationSpeed * frameTimeInMS);
144         render();
145         swapBuffers();
146
147         renderTimeInMS = RUNTIME_IN_MS() - frameStartTimeInMS;
148
149         if (renderTimeInMS < m_timerIntervalInMs)
150         {
151             usleep((m_timerIntervalInMs - renderTimeInMS) * 1000);
152         }
153
154         frameEndTimeInMS = RUNTIME_IN_MS();
155     }
156 }
157
158 bool OpenGLES2App::createWLContext(SurfaceConfiguration* config)
159 {
160     t_ilm_bool result = ILM_TRUE;
161     int width = config->surfaceWidth;
162     int height = config->surfaceHeight;
163
164     memset(&m_wlContextStruct, 0, sizeof(m_wlContextStruct));
165
166     m_wlContextStruct.width = width;
167     m_wlContextStruct.height = height;
168     m_wlContextStruct.wlDisplay = wl_display_connect(NULL);
169     if (NULL == m_wlContextStruct.wlDisplay)
170     {
171         cout<<"Error: wl_display_connect() failed.\n";
172     }
173
174     m_wlContextStruct.wlRegistry = wl_display_get_registry(m_wlContextStruct.wlDisplay);
175     wl_registry_add_listener(m_wlContextStruct.wlRegistry, &registry_listener, &m_wlContextStruct);
176     wl_display_dispatch(m_wlContextStruct.wlDisplay);
177     wl_display_roundtrip(m_wlContextStruct.wlDisplay);
178
179     m_wlContextStruct.wlSurface = wl_compositor_create_surface(m_wlContextStruct.wlCompositor);
180     if (NULL == m_wlContextStruct.wlSurface)
181     {
182         cout<<"Error: wl_compositor_create_surface() failed.\n";
183         destroyWLContext();
184     }
185
186     m_wlContextStruct.wlNativeWindow = wl_egl_window_create(m_wlContextStruct.wlSurface, width, height);
187     if (NULL == m_wlContextStruct.wlNativeWindow)
188     {
189         cout<<"Error: wl_egl_window_create() failed"<<endl;
190         destroyWLContext();
191     }
192
193     return result;
194 }
195
196 bool OpenGLES2App::createEGLContext()
197 {
198     t_ilm_bool result = ILM_TRUE;
199     EGLint eglstatus = EGL_SUCCESS;
200     m_eglContextStruct.eglDisplay = NULL;
201     m_eglContextStruct.eglSurface = NULL;
202     m_eglContextStruct.eglContext = NULL;
203
204     m_eglContextStruct.eglDisplay = eglGetDisplay(m_wlContextStruct.wlDisplay);
205     eglstatus = eglGetError();
206     if (!m_eglContextStruct.eglDisplay)
207     {
208         cout << "Error: eglGetDisplay() failed.\n";
209     }
210
211     EGLint iMajorVersion, iMinorVersion;
212     if (!eglInitialize(m_eglContextStruct.eglDisplay, &iMajorVersion,
213             &iMinorVersion))
214     {
215         cout << "Error: eglInitialize() failed.\n";
216     }
217
218     eglBindAPI(EGL_OPENGL_ES_API);
219     eglstatus = eglGetError();
220     if (eglstatus != EGL_SUCCESS)
221     {
222         cout << "Error: eglBindAPI() failed.\n";
223     }
224     EGLint pi32ConfigAttribs[] = {
225         EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
226         EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
227         EGL_RED_SIZE,   8,
228         EGL_GREEN_SIZE, 8,
229         EGL_BLUE_SIZE,  8,
230         EGL_ALPHA_SIZE, 8,
231         EGL_DEPTH_SIZE, 24,
232         EGL_STENCIL_SIZE, 8,
233         EGL_NONE };
234
235     int iConfigs;
236
237     if (!eglChooseConfig(m_eglContextStruct.eglDisplay, pi32ConfigAttribs, &m_eglContextStruct.eglConfig, 1, &iConfigs) || (iConfigs != 1))
238     {
239         cout << "Error: eglChooseConfig() failed.\n";
240     }
241
242     m_eglContextStruct.eglSurface = eglCreateWindowSurface(
243             m_eglContextStruct.eglDisplay, m_eglContextStruct.eglConfig,
244             m_wlContextStruct.wlNativeWindow, NULL);
245     eglstatus = eglGetError();
246
247     if (eglstatus != EGL_SUCCESS)
248     {
249         cout << "Error: eglCreateWindowSurface() failed.\n";
250     }
251
252     EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
253
254     m_eglContextStruct.eglContext = eglCreateContext(
255             m_eglContextStruct.eglDisplay, m_eglContextStruct.eglConfig, NULL,
256             contextAttribs);
257
258     eglstatus = eglGetError();
259     if (eglstatus != EGL_SUCCESS)
260     {
261         cout << "Error: eglCreateContext() failed.\n";
262     }
263
264     eglMakeCurrent(m_eglContextStruct.eglDisplay,
265             m_eglContextStruct.eglSurface, m_eglContextStruct.eglSurface,
266             m_eglContextStruct.eglContext);
267     eglSwapInterval(m_eglContextStruct.eglDisplay, 1);
268     eglstatus = eglGetError();
269     if (eglstatus != EGL_SUCCESS)
270     {
271         cout << "Error: eglMakeCurrent() failed.\n";
272     }
273
274     return result;
275 }
276
277 bool OpenGLES2App::setupLayerMangement(SurfaceConfiguration* config)
278 {
279     ilmErrorTypes error = ILM_FAILED;
280
281     // register surfaces to layermanager
282     t_ilm_layer layerid = (t_ilm_layer)config->layerId;//LAYER_EXAMPLE_GLES_APPLICATIONS;
283     t_ilm_surface surfaceid = (t_ilm_surface)config->surfaceId;//SURFACE_EXAMPLE_EGLX11_APPLICATION;
284     int width = config->surfaceWidth;
285     int height = config->surfaceHeight;
286     int posX = config->surfacePosX;
287     int posY = config->surfacePosY;
288     float opacity = config->opacity;
289
290     if (config->nosky)
291     {
292         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
293     }
294     else
295     {
296         glClearColor(0.2f, 0.2f, 0.5f, 1.0f);
297     }
298     // TODO: auto generate surface id
299     cout << "creating surface " << surfaceid << "\n";
300     struct wl_object* p_obj = (struct wl_object*)m_wlContextStruct.wlSurface;
301     uint32_t native_ilm_handle = 0;
302     native_ilm_handle = (m_wlContextStruct.connect_id << 16) | (uint32_t)p_obj->id;
303     cout<<"create a surface 0x"<<(t_ilm_nativehandle) native_ilm_handle<<"\n";
304     error = ilm_surfaceCreate( (t_ilm_nativehandle) native_ilm_handle, width, height,
305             ILM_PIXELFORMAT_RGBA_8888, &surfaceid);
306
307     cout << "set surface " << surfaceid << " dest region " << posX << ", " << posY << ", " << width << ", " << height << "\n";
308     ilm_surfaceSetDestinationRectangle(surfaceid, posX, posY, width, height);
309
310     cout << "set surface " << surfaceid << " src region " << 0 << ", " << 0 << ", " << width << ", " << height << "\n";
311     error = ilm_surfaceSetSourceRectangle(surfaceid, 0, 0, width, height);
312
313     cout << "Set surface " << surfaceid << " visible\n";
314     error = ilm_surfaceSetVisibility(surfaceid, ILM_TRUE);
315
316     cout << "Set surface " << surfaceid << " opacity " << opacity << "\n";
317     ilm_surfaceSetOpacity(surfaceid, opacity);
318
319     cout << "add surface " << surfaceid << " to layer " << layerid << "\n";
320     error = ilm_layerAddSurface(layerid, surfaceid);
321
322     cout << "commit\n";
323     error = ilm_commitChanges();
324
325     return ILM_TRUE;
326 }
327
328 void OpenGLES2App::destroyEglContext()
329 {
330     if (m_eglContextStruct.eglDisplay != NULL)
331     {
332         eglMakeCurrent(m_eglContextStruct.eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
333         eglTerminate(m_eglContextStruct.eglDisplay);
334     }
335 }
336
337 void OpenGLES2App::destroyWLContext()
338 {
339     if (m_wlContextStruct.wlNativeWindow)
340     {
341         wl_egl_window_destroy(m_wlContextStruct.wlNativeWindow);
342     }
343     if (m_wlContextStruct.wlSurface)
344     {
345         wl_surface_destroy(m_wlContextStruct.wlSurface);
346     }
347     if (m_wlContextStruct.wlCompositor)
348     {
349         wl_compositor_destroy(m_wlContextStruct.wlCompositor);
350     }
351 }
352
353 unsigned int OpenGLES2App::GetTickCount()
354 {
355     struct timeval ts;
356     gettimeofday(&ts, 0);
357     return (t_ilm_uint) (ts.tv_sec * 1000 + (ts.tv_usec / 1000));
358 }
359
360 extern "C" void
361 OpenGLES2App::frame_listener_func(void *data, struct wl_callback *callback, uint32_t time)
362 {
363     data = data; // TODO:to avoid warning
364     time = time; // TODO:to avoid warning
365     if (callback)
366     {
367         wl_callback_destroy(callback);
368     }
369 }
370
371 static const struct wl_callback_listener frame_listener = {
372     OpenGLES2App::frame_listener_func   
373 };
374
375 void OpenGLES2App::swapBuffers()
376 {
377     eglSwapBuffers(m_eglContextStruct.eglDisplay, m_eglContextStruct.eglSurface);
378
379     struct wl_callback* callback = wl_surface_frame(m_wlContextStruct.wlSurface);
380     wl_callback_add_listener(callback, &frame_listener, NULL);
381     wl_surface_commit(m_wlContextStruct.wlSurface);
382     wl_display_flush(m_wlContextStruct.wlDisplay);
383 }