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