Dali 3D User Interface Engine
egl-implementation.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 
18 
19 // CLASS HEADER
20 #include <gl/egl-implementation.h>
21 
22 // EXTERNAL INCLUDES
26 
27 // INTERNAL INCLUDES
28 #include <gl/gl-implementation.h>
29 #include <gl/egl-debug.h>
30 
31 namespace Dali
32 {
33 
34 namespace Internal
35 {
36 
37 namespace Adaptor
38 {
39 
40 #define TEST_EGL_ERROR(lastCommand) \
41 { \
42  EGLint err = eglGetError(); \
43  if (err != EGL_SUCCESS) \
44  { \
45  DALI_LOG_ERROR("EGL error after %s\n", lastCommand); \
46  Egl::PrintError(err); \
47  DALI_ASSERT_ALWAYS(0 && "EGL error"); \
48  } \
49 }
50 
52  : mEglNativeDisplay(0),
53  mEglNativeWindow(0),
54  mCurrentEglNativePixmap(0),
55  mEglDisplay(0),
56  mEglConfig(0),
57  mEglContext(0),
58  mCurrentEglSurface(0),
59  mGlesInitialized(false),
60  mIsOwnSurface(true),
61  mContextCurrent(false),
62  mIsWindow(true),
63  mColorDepth(COLOR_DEPTH_24)
64 {
65 }
66 
68 {
69  TerminateGles();
70 }
71 
72 bool EglImplementation::InitializeGles( EGLNativeDisplayType display, bool isOwnSurface )
73 {
74  if ( !mGlesInitialized )
75  {
76  mEglNativeDisplay = display;
77 
78  //@todo see if we can just EGL_DEFAULT_DISPLAY instead
79  mEglDisplay = eglGetDisplay(mEglNativeDisplay);
80  EGLint error = eglGetError();
81 
82  if( mEglDisplay == NULL && error != EGL_SUCCESS )
83  {
84  throw Dali::DaliException( "", "OpenGL ES is not supported");
85  }
86 
87  EGLint majorVersion = 0;
88  EGLint minorVersion = 0;
89  if ( !eglInitialize( mEglDisplay, &majorVersion, &minorVersion ) )
90  {
91  return false;
92  }
93  eglBindAPI(EGL_OPENGL_ES_API);
94 
96 
97 #if DALI_GLES_VERSION >= 30
98 
100  mContextAttribs.PushBack( EGL_CONTEXT_MAJOR_VERSION_KHR );
101  mContextAttribs.PushBack( DALI_GLES_VERSION / 10 );
102  mContextAttribs.PushBack( EGL_CONTEXT_MINOR_VERSION_KHR );
103  mContextAttribs.PushBack( DALI_GLES_VERSION % 10 );
104 
105 #else // DALI_GLES_VERSION >= 30
106 
108  mContextAttribs.PushBack( EGL_CONTEXT_CLIENT_VERSION );
110 
111 #endif // DALI_GLES_VERSION >= 30
112 
113  mContextAttribs.PushBack( EGL_NONE );
114 
115  mGlesInitialized = true;
116  mIsOwnSurface = isOwnSurface;
117  }
118 
119  return mGlesInitialized;
120 }
121 
123 {
124  // make sure a context isn't created twice
125  DALI_ASSERT_ALWAYS( (mEglContext == 0) && "EGL context recreated" );
126 
127  mEglContext = eglCreateContext(mEglDisplay, mEglConfig, NULL, &(mContextAttribs[0]));
128  TEST_EGL_ERROR("eglCreateContext render thread");
129 
130  DALI_ASSERT_ALWAYS( EGL_NO_CONTEXT != mEglContext && "EGL context not created" );
131 
132  DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_VENDOR : %s ***\n", glGetString(GL_VENDOR));
133  DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_RENDERER : %s ***\n", glGetString(GL_RENDERER));
134  DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_VERSION : %s ***\n", glGetString(GL_VERSION));
135  DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_SHADING_LANGUAGE_VERSION : %s***\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
136  DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** Supported Extensions ***\n%s\n\n", glGetString(GL_EXTENSIONS));
137 
138  return true;
139 }
140 
142 {
143  DALI_ASSERT_ALWAYS( mEglContext && "no EGL context" );
144 
145  eglDestroyContext( mEglDisplay, mEglContext );
146  mEglContext = 0;
147 }
148 
150 {
152  {
153  eglDestroySurface( mEglDisplay, mCurrentEglSurface );
154  mCurrentEglSurface = 0;
155  }
156 }
157 
159 {
160  mContextCurrent = true;
161 
162  if(mIsOwnSurface)
163  {
165  }
166 
167  EGLint error = eglGetError();
168 
169  if ( error != EGL_SUCCESS )
170  {
171  Egl::PrintError(error);
172 
173  DALI_ASSERT_ALWAYS(false && "MakeContextCurrent failed!");
174  }
175 
176  // We want to display this information all the time, so use the LogMessage directly
178  " Vendor: %s\n"
179  " Version: %s\n"
180  " Client APIs: %s\n"
181  " Extensions: %s\n",
182  eglQueryString(mEglDisplay, EGL_VENDOR),
183  eglQueryString(mEglDisplay, EGL_VERSION),
184  eglQueryString(mEglDisplay, EGL_CLIENT_APIS),
185  eglQueryString(mEglDisplay, EGL_EXTENSIONS));
186 }
187 
188 void EglImplementation::MakeCurrent( EGLNativePixmapType pixmap, EGLSurface eglSurface )
189 {
190  mCurrentEglNativePixmap = pixmap;
191  mCurrentEglSurface = eglSurface;
192 
193  if(mIsOwnSurface)
194  {
196  }
197 
198  EGLint error = eglGetError();
199 
200  if ( error != EGL_SUCCESS )
201  {
202  Egl::PrintError(error);
203 
204  DALI_ASSERT_ALWAYS(false && "MakeCurrent failed!");
205  }
206 }
207 
209 {
210  mContextCurrent = false;
211  // clear the current context
212  eglMakeCurrent( mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
213 }
214 
216 {
217  if ( mGlesInitialized )
218  {
219  // in latest Mali DDK (r2p3 ~ r3p0 in April, 2012),
220  // MakeContextNull should be called before eglDestroy surface
221  // to prevent crash in _mali_surface_destroy_callback
222  MakeContextNull();
223 
225  {
226  eglDestroySurface(mEglDisplay, mCurrentEglSurface);
227  }
228  eglDestroyContext(mEglDisplay, mEglContext);
229 
230  eglTerminate(mEglDisplay);
231 
232  mEglDisplay = NULL;
233  mEglConfig = NULL;
234  mEglContext = NULL;
235  mCurrentEglSurface = NULL;
236 
237  mGlesInitialized = false;
238  }
239 }
240 
242 {
243  return mGlesInitialized;
244 }
245 
247 {
248  eglSwapBuffers( mEglDisplay, mCurrentEglSurface );
249 }
250 
252 {
254 }
255 
257 {
258  eglWaitGL();
259 }
260 
261 void EglImplementation::ChooseConfig( bool isWindowType, ColorDepth depth )
262 {
263  if(mEglConfig && isWindowType == mIsWindow && mColorDepth == depth)
264  {
265  return;
266  }
267 
268  mIsWindow = isWindowType;
269 
270  EGLint numConfigs;
271  Vector<EGLint> configAttribs;
272  configAttribs.Reserve(31);
273 
274  if(isWindowType)
275  {
276  configAttribs.PushBack( EGL_SURFACE_TYPE );
277  configAttribs.PushBack( EGL_WINDOW_BIT );
278  }
279  else
280  {
281  configAttribs.PushBack( EGL_SURFACE_TYPE );
282  configAttribs.PushBack( EGL_PIXMAP_BIT );
283  }
284 
285  configAttribs.PushBack( EGL_RENDERABLE_TYPE );
286 
287 #if DALI_GLES_VERSION >= 30
288 
289 #ifdef _ARCH_ARM_
290  configAttribs.PushBack( EGL_OPENGL_ES3_BIT_KHR );
291 #else
292  // There is a bug in the desktop emulator
293  // Requesting for ES3 causes eglCreateContext even though it allows to ask
294  // for a configuration that supports GLES 3.0
295  configAttribs.PushBack( EGL_OPENGL_ES2_BIT );
296 #endif // _ARCH_ARM_
297 
298 #else // DALI_GLES_VERSION >= 30
299 
300  DALI_LOG_WARNING( "Using OpenGL ES 2 \n" );
301  configAttribs.PushBack( EGL_OPENGL_ES2_BIT );
302 
303 #endif //DALI_GLES_VERSION >= 30
304 
305 #if DALI_GLES_VERSION >= 30
306 // TODO: enable this flag when it becomes supported
307 // configAttribs.PushBack( EGL_CONTEXT_FLAGS_KHR );
308 // configAttribs.PushBack( EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR );
309 #endif //DALI_GLES_VERSION >= 30
310 
311  configAttribs.PushBack( EGL_RED_SIZE );
312  configAttribs.PushBack( 8 );
313  configAttribs.PushBack( EGL_GREEN_SIZE );
314  configAttribs.PushBack( 8 );
315  configAttribs.PushBack( EGL_BLUE_SIZE );
316  configAttribs.PushBack( 8 );
317 
318  configAttribs.PushBack( EGL_ALPHA_SIZE );
319 #ifdef _ARCH_ARM_
320  configAttribs.PushBack( (depth == COLOR_DEPTH_32) ? 8 : 0 );
321 #else
322  // There is a bug in the desktop emulator
323  // setting EGL_ALPHA_SIZE to 8 results in eglChooseConfig failing
324  configAttribs.PushBack( 0 );
325 #endif // _ARCH_ARM_
326 
327  configAttribs.PushBack( EGL_DEPTH_SIZE );
328  configAttribs.PushBack( 24 );
329  configAttribs.PushBack( EGL_STENCIL_SIZE );
330  configAttribs.PushBack( 8 );
331 #ifndef DALI_PROFILE_UBUNTU
332  configAttribs.PushBack( EGL_SAMPLES );
333  configAttribs.PushBack( 4 );
334  configAttribs.PushBack( EGL_SAMPLE_BUFFERS );
335  configAttribs.PushBack( 1 );
336 #endif // DALI_PROFILE_UBUNTU
337  configAttribs.PushBack( EGL_NONE );
338 
339  if ( eglChooseConfig( mEglDisplay, &(configAttribs[0]), &mEglConfig, 1, &numConfigs ) != EGL_TRUE )
340  {
341  EGLint error = eglGetError();
342  switch (error)
343  {
344  case EGL_BAD_DISPLAY:
345  {
346  DALI_LOG_ERROR("Display is not an EGL display connection\n");
347  break;
348  }
349  case EGL_BAD_ATTRIBUTE:
350  {
351  DALI_LOG_ERROR("The parameter configAttribs contains an invalid frame buffer configuration attribute or an attribute value that is unrecognized or out of range\n");
352  break;
353  }
354  case EGL_NOT_INITIALIZED:
355  {
356  DALI_LOG_ERROR("Display has not been initialized\n");
357  break;
358  }
359  case EGL_BAD_PARAMETER:
360  {
361  DALI_LOG_ERROR("The parameter numConfig is NULL\n");
362  break;
363  }
364  default:
365  {
366  DALI_LOG_ERROR("Unknown error.\n");
367  }
368  }
369  DALI_ASSERT_ALWAYS(false && "eglChooseConfig failed!");
370  }
371 
372  if ( numConfigs != 1 )
373  {
374  DALI_LOG_ERROR("No configurations found.\n");
375 
376  TEST_EGL_ERROR("eglChooseConfig");
377  }
378 }
379 
380 void EglImplementation::CreateSurfaceWindow( EGLNativeWindowType window, ColorDepth depth )
381 {
382  DALI_ASSERT_ALWAYS( ( mCurrentEglSurface == 0 ) && "EGL surface already exists" );
383 
384  mEglNativeWindow = window;
385  mColorDepth = depth;
386  mIsWindow = true;
387 
388  // egl choose config
390 
391  mCurrentEglSurface = eglCreateWindowSurface( mEglDisplay, mEglConfig, mEglNativeWindow, NULL );
392  TEST_EGL_ERROR("eglCreateWindowSurface");
393 
394  DALI_ASSERT_ALWAYS( mCurrentEglSurface && "Create window surface failed" );
395 }
396 
397 EGLSurface EglImplementation::CreateSurfacePixmap( EGLNativePixmapType pixmap, ColorDepth depth )
398 {
399  mCurrentEglNativePixmap = pixmap;
400  mColorDepth = depth;
401  mIsWindow = false;
402 
403  // egl choose config
405 
406  mCurrentEglSurface = eglCreatePixmapSurface( mEglDisplay, mEglConfig, mCurrentEglNativePixmap, NULL );
407  TEST_EGL_ERROR("eglCreatePixmapSurface");
408 
409  DALI_ASSERT_ALWAYS( mCurrentEglSurface && "Create pixmap surface failed" );
410 
411  return mCurrentEglSurface;
412 }
413 
414 bool EglImplementation::ReplaceSurfaceWindow( EGLNativeWindowType window )
415 {
416  bool contextLost = false;
417 
418  // display connection has not changed, then we can just create a new surface
419  // the surface is bound to the context, so set the context to null
420  MakeContextNull();
421 
422  // destroy the surface
423  DestroySurface();
424 
425  // create the EGL surface
426  CreateSurfaceWindow( window, mColorDepth );
427 
428  // set the context to be current with the new surface
430 
431  return contextLost;
432 }
433 
434 bool EglImplementation::ReplaceSurfacePixmap( EGLNativePixmapType pixmap, EGLSurface& eglSurface )
435 {
436  bool contextLost = false;
437 
438  // display connection has not changed, then we can just create a new surface
439  // create the EGL surface
440  eglSurface = CreateSurfacePixmap( pixmap, mColorDepth );
441 
442  // set the eglSurface to be current
443  MakeCurrent( pixmap, eglSurface );
444 
445  return contextLost;
446 }
447 
449 {
450  return mEglDisplay;
451 }
452 
454 {
455  return mEglContext;
456 }
457 
458 } // namespace Adaptor
459 
460 } // namespace Internal
461 
462 } // namespace Dali
Dali Docs Home
Read more about Dali