1 /***************************************************************************
3 * Copyright 2010,2011 BMW Car IT GmbH
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 ****************************************************************************/
19 #include "OpenGLES2App.h"
20 #include "LayerScene.h"
21 #include <ilm_client.h>
31 // Max width and height of the window
32 #define SURFACE_WIDTH 800
33 #define SURFACE_HEIGHT 480
35 #define LAYER_WIDTH 800
36 #define LAYER_HEIGHT 480
39 OpenGLES2App::OpenGLES2App(float fps, float animationSpeed)
40 : m_framesPerSecond(fps)
41 , m_animationSpeed(animationSpeed)
42 , m_timerIntervalInMs(1000.0 / m_framesPerSecond)
45 createX11Context(SURFACE_WIDTH, SURFACE_HEIGHT);
46 createEGLContext(SURFACE_WIDTH, SURFACE_HEIGHT);
48 glClearColor(0.2f, 0.2f, 0.5f, 1.0f);
49 //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
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);
63 OpenGLES2App::~OpenGLES2App()
70 void OpenGLES2App::mainloop()
72 unsigned int startTime = GetTickCount();
73 unsigned int currentTime = 0;
74 unsigned int previousTime = 0;
75 unsigned int lastFrameTime = 0;
79 previousTime = currentTime;
80 currentTime = GetTickCount() - startTime;
81 lastFrameTime = currentTime - previousTime;
83 update(m_animationSpeed * currentTime, m_animationSpeed * lastFrameTime);
87 usleep(m_timerIntervalInMs * 1000);
91 bool OpenGLES2App::createX11Context(int width, int height)
93 t_ilm_bool result = ILM_TRUE;
95 XSetWindowAttributes windowAttributes;
96 unsigned int windowMask;
98 int widthCorrected, heightCorrected;
100 m_x11ContextStruct.x11Window = 0;
101 m_x11ContextStruct.x11Display = NULL;
102 m_x11ContextStruct.x11Screen = 0;
103 m_x11ContextStruct.x11Visual = NULL;
105 m_x11ContextStruct.x11Display = XOpenDisplay(0);
106 if (!m_x11ContextStruct.x11Display)
108 cout << "Error: Unable to open X display\n";
111 m_x11ContextStruct.x11Screen = XDefaultScreen(m_x11ContextStruct.x11Display);
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);
117 // Alloc memory for the visual info
118 m_x11ContextStruct.x11Visual = (XVisualInfo*) malloc(sizeof(XVisualInfo));
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))
125 cout << "Error: Unable to acquire visual\n";
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;
136 // Add to these for handling other events
137 windowAttributes.event_mask = StructureNotifyMask | ExposureMask
138 | ButtonPressMask | ButtonReleaseMask | KeyPressMask
140 windowAttributes.backing_store = Always;
142 // Set the window mask attributes
143 windowMask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap
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);
154 // Creates the X11 window
155 m_x11ContextStruct.x11Window
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,
165 XMapWindow(m_x11ContextStruct.x11Display, m_x11ContextStruct.x11Window);
166 XFlush(m_x11ContextStruct.x11Display);
170 bool OpenGLES2App::createEGLContext(int width, int height)
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;
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)
182 cout << "Error: eglGetDisplay() failed.\n";
185 EGLint iMajorVersion, iMinorVersion;
186 if (!eglInitialize(m_eglContextStruct.eglDisplay, &iMajorVersion,
189 cout << "Error: eglInitialize() failed.\n";
191 eglBindAPI(EGL_OPENGL_ES_API);
192 eglstatus = eglGetError();
193 if (eglstatus != EGL_SUCCESS)
195 cout << "Error: eglBindAPI() failed.\n";
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 };
202 if (!eglChooseConfig(m_eglContextStruct.eglDisplay, pi32ConfigAttribs, &m_eglContextStruct.eglConfig, 1, &iConfigs) || (iConfigs != 1))
204 cout << "Error: eglChooseConfig() failed.\n";
207 m_eglContextStruct.eglSurface = eglCreateWindowSurface(
208 m_eglContextStruct.eglDisplay, m_eglContextStruct.eglConfig,
209 (EGLNativeWindowType) m_x11ContextStruct.x11Window, NULL);
210 eglstatus = eglGetError();
212 if (eglstatus != EGL_SUCCESS)
214 cout << "Error: eglCreateWindowSurface() failed.\n";
217 EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
219 m_eglContextStruct.eglContext = eglCreateContext(
220 m_eglContextStruct.eglDisplay, m_eglContextStruct.eglConfig, NULL,
223 eglstatus = eglGetError();
224 if (eglstatus != EGL_SUCCESS)
226 cout << "Error: eglCreateContext() failed.\n";
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)
236 cout << "Error: eglMakeCurrent() failed.\n";
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;
243 // TODO: if (error == ILM_FAILED) return ILM_FALSE;
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);
249 // TODO: if (error == ILM_FAILED) return ILM_FALSE;
251 cout << "set surface dest region\n";
252 error = ilm_surfaceSetDestinationRectangle(surfaceid, 0, 0, width, height);
254 // TODO: if (error == ILM_FAILED) return ILM_FALSE;
256 cout << "set surface src region\n";
257 error = ilm_surfaceSetSourceRectangle(surfaceid, 0, 0, width, height);
259 // TODO: if (error == ILM_FAILED) return ILM_FALSE;
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);
268 //if (error == ILM_FAILED) return ILM_FALSE;
271 error = ilm_commitChanges();
273 //if (error == ILM_FAILED) return ILM_FALSE;
278 void OpenGLES2App::destroyEglContext()
280 if (m_eglContextStruct.eglDisplay != NULL)
282 eglMakeCurrent(m_eglContextStruct.eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
283 eglTerminate(m_eglContextStruct.eglDisplay);
287 void OpenGLES2App::destroyX11Context()
289 if (m_x11ContextStruct.x11Window)
291 XDestroyWindow(m_x11ContextStruct.x11Display, m_x11ContextStruct.x11Window);
294 if (m_x11ContextStruct.x11Colormap)
296 XFreeColormap(m_x11ContextStruct.x11Display, m_x11ContextStruct.x11Colormap);
299 if (m_x11ContextStruct.x11Display)
301 XCloseDisplay(m_x11ContextStruct.x11Display);
304 if (m_x11ContextStruct.x11Visual)
306 free(m_x11ContextStruct.x11Visual);
310 unsigned int OpenGLES2App::GetTickCount()
313 gettimeofday(&ts, 0);
314 return (t_ilm_uint) (ts.tv_sec * 1000 + (ts.tv_usec / 1000));
317 void OpenGLES2App::swapBuffers()
319 eglSwapBuffers(m_eglContextStruct.eglDisplay, m_eglContextStruct.eglSurface);