Enabled depth buffer allocation.
[profile/ivi/layer-management.git] / LayerManagerExamples / EGLX11MockNavigation / src / OpenGLES2App.cpp
1 /***************************************************************************
2  *
3  * Copyright 2010,2011 BMW Car IT GmbH
4  *
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  ****************************************************************************/
19 #include "OpenGLES2App.h"
20 #include "LayerScene.h"
21 #include <ilm_client.h>
22
23 #include <iostream>
24 using std::cout;
25 using std::endl;
26
27 #include <stdlib.h>
28 #include <math.h>
29 #include <sys/time.h>
30
31 // Max width and height of the window
32 #define SURFACE_WIDTH  800
33 #define SURFACE_HEIGHT 480
34
35 #define LAYER_WIDTH    800
36 #define LAYER_HEIGHT   480
37
38
39 OpenGLES2App::OpenGLES2App(float fps, float animationSpeed)
40 : m_framesPerSecond(fps)
41 , m_animationSpeed(animationSpeed)
42 , m_timerIntervalInMs(1000.0 / m_framesPerSecond)
43 {
44     ilm_init();
45     createX11Context(SURFACE_WIDTH, SURFACE_HEIGHT);
46     createEGLContext(SURFACE_WIDTH, SURFACE_HEIGHT);
47
48     glClearColor(0.2f, 0.2f, 0.5f, 1.0f);
49     //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
50     //glEnable(GL_BLEND);
51     glDisable(GL_BLEND);
52
53     glClearDepthf(1.0f);
54     glCullFace(GL_BACK);
55     glDisable(GL_CULL_FACE);
56     // Enable z-buffer test
57     // We are using a projection matrix optimized for a floating point depth buffer,
58     // so the depth test and clear value need to be inverted (1 becomes near, 0 becomes far).
59     glEnable(GL_DEPTH_TEST);
60     glDepthFunc(GL_LEQUAL);
61 }
62
63 OpenGLES2App::~OpenGLES2App()
64 {
65     destroyEglContext();
66     destroyX11Context();
67     ilm_destroy();
68 }
69
70 void OpenGLES2App::mainloop()
71 {
72         unsigned int startTime = GetTickCount();
73     unsigned int currentTime = 0;
74     unsigned int previousTime = 0;
75     unsigned int lastFrameTime = 0;
76
77     while (true)
78     {
79         previousTime = currentTime;
80         currentTime = GetTickCount() - startTime;
81         lastFrameTime = currentTime - previousTime;
82
83         update(m_animationSpeed * currentTime, m_animationSpeed * lastFrameTime);
84         render();
85         swapBuffers();
86
87         usleep(m_timerIntervalInMs * 1000);
88     }
89 }
90
91 bool OpenGLES2App::createX11Context(int width, int height)
92 {
93     t_ilm_bool result = ILM_TRUE;
94     Window rootWindow;
95     XSetWindowAttributes windowAttributes;
96     unsigned int windowMask;
97     int colorDepth;
98     int widthCorrected, heightCorrected;
99
100     m_x11ContextStruct.x11Window = 0;
101     m_x11ContextStruct.x11Display = NULL;
102     m_x11ContextStruct.x11Screen = 0;
103     m_x11ContextStruct.x11Visual = NULL;
104
105     m_x11ContextStruct.x11Display = XOpenDisplay(0);
106     if (!m_x11ContextStruct.x11Display)
107     {
108         cout << "Error: Unable to open X display\n";
109         return ILM_FALSE;
110     }
111     m_x11ContextStruct.x11Screen = XDefaultScreen(m_x11ContextStruct.x11Display);
112
113     // Get the root window parameters
114     rootWindow = RootWindow(m_x11ContextStruct.x11Display, m_x11ContextStruct.x11Screen);
115     colorDepth = 32; // TODO: DefaultDepth(m_x11ContextStruct.x11Display, m_x11ContextStruct.x11Screen);
116
117     // Alloc memory for the visual info
118     m_x11ContextStruct.x11Visual = (XVisualInfo*) malloc(sizeof(XVisualInfo));
119
120     // Try to find a visual which is matching the needed parameters
121     if (!XMatchVisualInfo(m_x11ContextStruct.x11Display,
122             m_x11ContextStruct.x11Screen, colorDepth, TrueColor,
123             m_x11ContextStruct.x11Visual))
124     {
125         cout << "Error: Unable to acquire visual\n";
126         destroyX11Context();
127         return ILM_FALSE;
128     }
129
130     // Create the rendercontext color map
131     m_x11ContextStruct.x11Colormap = XCreateColormap(
132             m_x11ContextStruct.x11Display, rootWindow,
133             m_x11ContextStruct.x11Visual->visual, AllocNone);
134     windowAttributes.colormap = m_x11ContextStruct.x11Colormap;
135
136     // Add to these for handling other events
137     windowAttributes.event_mask = StructureNotifyMask | ExposureMask
138             | ButtonPressMask | ButtonReleaseMask | KeyPressMask
139             | KeyReleaseMask;
140     windowAttributes.backing_store = Always;
141
142     // Set the window mask attributes
143     windowMask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap
144             | CWBackingStore;
145
146     // get the corrected window dimensions
147     widthCorrected = width < XDisplayWidth(m_x11ContextStruct.x11Display,
148             m_x11ContextStruct.x11Screen) ? width : XDisplayWidth(
149             m_x11ContextStruct.x11Display, m_x11ContextStruct.x11Screen);
150     heightCorrected = height < XDisplayHeight(m_x11ContextStruct.x11Display,
151             m_x11ContextStruct.x11Screen) ? height : XDisplayHeight(
152             m_x11ContextStruct.x11Display, m_x11ContextStruct.x11Screen);
153
154     // Creates the X11 window
155     m_x11ContextStruct.x11Window
156             = XCreateWindow(
157                     m_x11ContextStruct.x11Display,
158                     RootWindow(m_x11ContextStruct.x11Display, m_x11ContextStruct.x11Screen),
159                     0, 0, widthCorrected, heightCorrected, 0,
160                     m_x11ContextStruct.x11Visual->depth, InputOutput,
161                     m_x11ContextStruct.x11Visual->visual, windowMask,
162                     &windowAttributes);
163
164     // map the window
165     XMapWindow(m_x11ContextStruct.x11Display, m_x11ContextStruct.x11Window);
166     XFlush(m_x11ContextStruct.x11Display);
167     return result;
168 }
169
170 bool OpenGLES2App::createEGLContext(int width, int height)
171 {
172     t_ilm_bool result = ILM_TRUE;
173     m_eglContextStruct.eglDisplay = NULL;
174     m_eglContextStruct.eglSurface = NULL;
175     m_eglContextStruct.eglContext = NULL;
176     ilmErrorTypes error = ILM_FAILED;
177
178     m_eglContextStruct.eglDisplay = eglGetDisplay((EGLNativeDisplayType) m_x11ContextStruct.x11Display); // TODO: remove all C style casts in C++ code; use C++ casts
179     EGLint eglstatus = eglGetError();
180     if (!m_eglContextStruct.eglDisplay)
181     {
182         cout << "Error: eglGetDisplay() failed.\n";
183     }
184
185     EGLint iMajorVersion, iMinorVersion;
186     if (!eglInitialize(m_eglContextStruct.eglDisplay, &iMajorVersion,
187             &iMinorVersion))
188     {
189         cout << "Error: eglInitialize() failed.\n";
190     }
191     eglBindAPI(EGL_OPENGL_ES_API);
192     eglstatus = eglGetError();
193     if (eglstatus != EGL_SUCCESS)
194     {
195         cout << "Error: eglBindAPI() failed.\n";
196     }
197
198     EGLint pi32ConfigAttribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE,
199                                    EGL_OPENGL_ES2_BIT, EGL_RED_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 1, EGL_NONE };
200     int iConfigs;
201
202     if (!eglChooseConfig(m_eglContextStruct.eglDisplay, pi32ConfigAttribs, &m_eglContextStruct.eglConfig, 1, &iConfigs) || (iConfigs != 1))
203     {
204         cout << "Error: eglChooseConfig() failed.\n";
205     }
206
207     m_eglContextStruct.eglSurface = eglCreateWindowSurface(
208             m_eglContextStruct.eglDisplay, m_eglContextStruct.eglConfig,
209             (EGLNativeWindowType) m_x11ContextStruct.x11Window, NULL);
210     eglstatus = eglGetError();
211
212     if (eglstatus != EGL_SUCCESS)
213     {
214         cout << "Error: eglCreateWindowSurface() failed.\n";
215     }
216
217     EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
218
219     m_eglContextStruct.eglContext = eglCreateContext(
220             m_eglContextStruct.eglDisplay, m_eglContextStruct.eglConfig, NULL,
221             contextAttribs);
222
223     eglstatus = eglGetError();
224     if (eglstatus != EGL_SUCCESS)
225     {
226         cout << "Error: eglCreateContext() failed.\n";
227     }
228
229     eglMakeCurrent(m_eglContextStruct.eglDisplay,
230             m_eglContextStruct.eglSurface, m_eglContextStruct.eglSurface,
231             m_eglContextStruct.eglContext);
232     eglSwapInterval(m_eglContextStruct.eglDisplay, 1);
233     eglstatus = eglGetError();
234     if (eglstatus != EGL_SUCCESS)
235     {
236         cout << "Error: eglMakeCurrent() failed.\n";
237     }
238
239     // register surfaces to layermanager
240     t_ilm_layer layerid = (t_ilm_layer)LAYER_EXAMPLE_GLES_APPLICATIONS;
241     t_ilm_surface surfaceid = (t_ilm_surface)SURFACE_EXAMPLE_EGLX11_APPLICATION;
242
243     // TODO: if (error == ILM_FAILED) return ILM_FALSE;
244
245     cout << "create a surface " << (t_ilm_nativehandle) m_x11ContextStruct.x11Window << "\n";
246     error = ilm_surfaceCreate( (t_ilm_nativehandle) m_x11ContextStruct.x11Window, width, height,
247             ILM_PIXELFORMAT_RGBA_8888, &surfaceid);
248
249     // TODO: if (error == ILM_FAILED) return ILM_FALSE;
250
251     cout << "set surface dest region\n";
252     error = ilm_surfaceSetDestinationRectangle(surfaceid, 0, 0, width, height);
253
254     // TODO: if (error == ILM_FAILED) return ILM_FALSE;
255
256     cout << "set surface src region\n";
257     error = ilm_surfaceSetSourceRectangle(surfaceid, 0, 0, width, height);
258
259     // TODO: if (error == ILM_FAILED) return ILM_FALSE;
260
261     cout << "add surface to layer\n";
262     error = ilm_layerAddSurface(layerid, surfaceid);
263     cout << "Set surface visible\n";
264     error = ilm_surfaceSetVisibility(surfaceid, ILM_TRUE);
265     cout << "Set surface opacity\n";
266     error = ilm_surfaceSetOpacity(surfaceid, 0.75f);
267
268     //if (error == ILM_FAILED) return ILM_FALSE;
269
270     cout << "commit\n";
271     error = ilm_commitChanges();
272
273     //if (error == ILM_FAILED) return ILM_FALSE;
274
275     return result;
276 }
277
278 void OpenGLES2App::destroyEglContext()
279 {
280     if (m_eglContextStruct.eglDisplay != NULL)
281     {
282         eglMakeCurrent(m_eglContextStruct.eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
283         eglTerminate(m_eglContextStruct.eglDisplay);
284     }
285 }
286
287 void OpenGLES2App::destroyX11Context()
288 {
289     if (m_x11ContextStruct.x11Window)
290     {
291         XDestroyWindow(m_x11ContextStruct.x11Display, m_x11ContextStruct.x11Window);
292     }
293
294     if (m_x11ContextStruct.x11Colormap)
295     {
296         XFreeColormap(m_x11ContextStruct.x11Display, m_x11ContextStruct.x11Colormap);
297     }
298
299     if (m_x11ContextStruct.x11Display)
300     {
301         XCloseDisplay(m_x11ContextStruct.x11Display);
302     }
303
304     if (m_x11ContextStruct.x11Visual)
305     {
306         free(m_x11ContextStruct.x11Visual);
307     }
308 }
309
310 unsigned int OpenGLES2App::GetTickCount()
311 {
312     struct timeval ts;
313     gettimeofday(&ts, 0);
314     return (t_ilm_uint) (ts.tv_sec * 1000 + (ts.tv_usec / 1000));
315 }
316
317 void OpenGLES2App::swapBuffers()
318 {
319     eglSwapBuffers(m_eglContextStruct.eglDisplay, m_eglContextStruct.eglSurface);
320 }