2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 #include <gl/egl-implementation.h>
23 #include <dali/integration-api/debug.h>
24 #include <dali/public-api/common/dali-common.h>
25 #include <dali/public-api/common/dali-vector.h>
28 #include <gl/gl-implementation.h>
33 void PrintEglError( EGLint error )
39 DALI_LOG_ERROR("EGL_BAD_DISPLAY : Display is not an EGL display connection\n");
42 case EGL_NOT_INITIALIZED:
44 DALI_LOG_ERROR("EGL_NOT_INITIALIZED : Display has not been initialized\n");
49 DALI_LOG_ERROR("EGL_BAD_SURFACE : Draw or read is not an EGL surface\n");
54 DALI_LOG_ERROR("EGL_BAD_CONTEXT : Context is not an EGL rendering context\n");
59 DALI_LOG_ERROR("EGL_BAD_MATCH : Draw or read are not compatible with context, or if context is set to EGL_NO_CONTEXT and draw or read are not set to EGL_NO_SURFACE, or if draw or read are set to EGL_NO_SURFACE and context is not set to EGL_NO_CONTEXT\n");
64 DALI_LOG_ERROR("EGL_BAD_ACCESS : Context is current to some other thread\n");
67 case EGL_BAD_NATIVE_PIXMAP:
69 DALI_LOG_ERROR("EGL_BAD_NATIVE_PIXMAP : A native pixmap underlying either draw or read is no longer valid\n");
72 case EGL_BAD_NATIVE_WINDOW:
74 DALI_LOG_ERROR("EGL_BAD_NATIVE_WINDOW : A native window underlying either draw or read is no longer valid\n");
77 case EGL_BAD_CURRENT_SURFACE:
79 DALI_LOG_ERROR("EGL_BAD_CURRENT_SURFACE : The previous context has unflushed commands and the previous surface is no longer valid\n");
84 DALI_LOG_ERROR("EGL_BAD_ALLOC : Allocation of ancillary buffers for draw or read were delayed until eglMakeCurrent is called, and there are not enough resources to allocate them\n");
87 case EGL_CONTEXT_LOST:
89 DALI_LOG_ERROR("EGL_CONTEXT_LOST : If a power management event has occurred. The application must destroy all contexts and reinitialise OpenGL ES state and objects to continue rendering\n");
94 DALI_LOG_ERROR("Unknown error with code: %d\n", error);
100 } // unnamed namespace
111 #define TEST_EGL_ERROR(lastCommand) \
113 EGLint err = eglGetError(); \
114 if (err != EGL_SUCCESS) \
116 DALI_LOG_ERROR("EGL error after %s\n", lastCommand); \
117 PrintEglError(err); \
118 DALI_ASSERT_ALWAYS(0 && "EGL error"); \
122 EglImplementation::EglImplementation()
123 : mEglNativeDisplay(0),
130 mGlesInitialized(false),
132 mContextCurrent(false),
134 mColorDepth(COLOR_DEPTH_24)
138 EglImplementation::~EglImplementation()
143 bool EglImplementation::InitializeGles( EGLNativeDisplayType display, bool isOwnSurface )
145 if ( !mGlesInitialized )
147 mEglNativeDisplay = display;
149 //@todo see if we can just EGL_DEFAULT_DISPLAY instead
150 mEglDisplay = eglGetDisplay(mEglNativeDisplay);
151 EGLint error = eglGetError();
153 if( mEglDisplay == NULL && error != EGL_SUCCESS )
155 throw Dali::DaliException( "", "OpenGL ES is not supported");
158 EGLint majorVersion = 0;
159 EGLint minorVersion = 0;
160 if ( !eglInitialize( mEglDisplay, &majorVersion, &minorVersion ) )
164 eglBindAPI(EGL_OPENGL_ES_API);
166 mContextAttribs.Clear();
168 #if DALI_GLES_VERSION >= 30
170 mContextAttribs.Reserve(5);
171 mContextAttribs.PushBack( EGL_CONTEXT_MAJOR_VERSION_KHR );
172 mContextAttribs.PushBack( 3 );
173 mContextAttribs.PushBack( EGL_CONTEXT_MINOR_VERSION_KHR );
174 mContextAttribs.PushBack( 0 );
176 #else // DALI_GLES_VERSION >= 30
178 mContextAttribs.Reserve(3);
179 mContextAttribs.PushBack( EGL_CONTEXT_CLIENT_VERSION );
180 mContextAttribs.PushBack( 2 );
182 #endif // DALI_GLES_VERSION >= 30
184 mContextAttribs.PushBack( EGL_NONE );
186 mGlesInitialized = true;
187 mIsOwnSurface = isOwnSurface;
190 return mGlesInitialized;
193 bool EglImplementation::CreateContext()
195 // make sure a context isn't created twice
196 DALI_ASSERT_ALWAYS( (mEglContext == 0) && "EGL context recreated" );
198 mEglContext = eglCreateContext(mEglDisplay, mEglConfig, NULL, &(mContextAttribs[0]));
199 TEST_EGL_ERROR("eglCreateContext render thread");
201 DALI_ASSERT_ALWAYS( EGL_NO_CONTEXT != mEglContext && "EGL context not created" );
203 DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_VENDOR : %s ***\n", glGetString(GL_VENDOR));
204 DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_RENDERER : %s ***\n", glGetString(GL_RENDERER));
205 DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_VERSION : %s ***\n", glGetString(GL_VERSION));
206 DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_SHADING_LANGUAGE_VERSION : %s***\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
207 DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** Supported Extensions ***\n%s\n\n", glGetString(GL_EXTENSIONS));
212 void EglImplementation::DestroyContext()
214 DALI_ASSERT_ALWAYS( mEglContext && "no EGL context" );
216 eglDestroyContext( mEglDisplay, mEglContext );
220 void EglImplementation::DestroySurface()
222 if(mIsOwnSurface && mEglSurface)
224 eglDestroySurface( mEglDisplay, mEglSurface );
229 void EglImplementation::MakeContextCurrent()
231 mContextCurrent = true;
235 eglMakeCurrent( mEglDisplay, mEglSurface, mEglSurface, mEglContext );
238 EGLint error = eglGetError();
240 if ( error != EGL_SUCCESS )
242 PrintEglError(error);
244 DALI_ASSERT_ALWAYS(false && "MakeContextCurrent failed!");
247 // We want to display this information all the time, so use the LogMessage directly
248 Integration::Log::LogMessage(Integration::Log::DebugInfo, "EGL Information\n"
253 eglQueryString(mEglDisplay, EGL_VENDOR),
254 eglQueryString(mEglDisplay, EGL_VERSION),
255 eglQueryString(mEglDisplay, EGL_CLIENT_APIS),
256 eglQueryString(mEglDisplay, EGL_EXTENSIONS));
259 void EglImplementation::MakeContextNull()
261 mContextCurrent = false;
262 // clear the current context
263 eglMakeCurrent( mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
266 void EglImplementation::TerminateGles()
268 if ( mGlesInitialized )
270 // in latest Mali DDK (r2p3 ~ r3p0 in April, 2012),
271 // MakeContextNull should be called before eglDestroy surface
272 // to prevent crash in _mali_surface_destroy_callback
275 if(mIsOwnSurface && mEglSurface)
277 eglDestroySurface(mEglDisplay, mEglSurface);
279 eglDestroyContext(mEglDisplay, mEglContext);
281 eglTerminate(mEglDisplay);
288 mGlesInitialized = false;
292 bool EglImplementation::IsGlesInitialized() const
294 return mGlesInitialized;
297 void EglImplementation::SwapBuffers()
299 eglSwapBuffers( mEglDisplay, mEglSurface );
302 void EglImplementation::CopyBuffers()
304 eglCopyBuffers( mEglDisplay, mEglSurface, mEglNativePixmap );
307 void EglImplementation::WaitGL()
312 void EglImplementation::ChooseConfig( bool isWindowType, ColorDepth depth )
314 if(mEglConfig && isWindowType == mIsWindow && mColorDepth == depth)
319 mIsWindow = isWindowType;
322 Vector<EGLint> configAttribs;
323 configAttribs.Reserve(31);
327 configAttribs.PushBack( EGL_SURFACE_TYPE );
328 configAttribs.PushBack( EGL_WINDOW_BIT );
332 configAttribs.PushBack( EGL_SURFACE_TYPE );
333 configAttribs.PushBack( EGL_PIXMAP_BIT );
336 configAttribs.PushBack( EGL_RENDERABLE_TYPE );
338 #if DALI_GLES_VERSION >= 30
341 configAttribs.PushBack( EGL_OPENGL_ES3_BIT_KHR );
343 // There is a bug in the desktop emulator
344 // Requesting for ES3 causes eglCreateContext even though it allows to ask
345 // for a configuration that supports GLES 3.0
346 configAttribs.PushBack( EGL_OPENGL_ES2_BIT );
349 #else // DALI_GLES_VERSION >= 30
351 DALI_LOG_WARNING( "Using OpenGL ES 2 \n" );
352 configAttribs.PushBack( EGL_OPENGL_ES2_BIT );
354 #endif //DALI_GLES_VERSION >= 30
356 #if DALI_GLES_VERSION >= 30
357 // TODO: enable this flag when it becomes supported
358 // configAttribs.PushBack( EGL_CONTEXT_FLAGS_KHR );
359 // configAttribs.PushBack( EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR );
360 #endif //DALI_GLES_VERSION >= 30
362 configAttribs.PushBack( EGL_RED_SIZE );
363 configAttribs.PushBack( 8 );
364 configAttribs.PushBack( EGL_GREEN_SIZE );
365 configAttribs.PushBack( 8 );
366 configAttribs.PushBack( EGL_BLUE_SIZE );
367 configAttribs.PushBack( 8 );
369 configAttribs.PushBack( EGL_ALPHA_SIZE );
371 configAttribs.PushBack( (depth == COLOR_DEPTH_32) ? 8 : 0 );
373 // There is a bug in the desktop emulator
374 // setting EGL_ALPHA_SIZE to 8 results in eglChooseConfig failing
375 configAttribs.PushBack( 0 );
378 configAttribs.PushBack( EGL_DEPTH_SIZE );
379 configAttribs.PushBack( 24 );
380 configAttribs.PushBack( EGL_STENCIL_SIZE );
381 configAttribs.PushBack( 8 );
382 #ifndef DALI_PROFILE_UBUNTU
383 configAttribs.PushBack( EGL_SAMPLES );
384 configAttribs.PushBack( 4 );
385 configAttribs.PushBack( EGL_SAMPLE_BUFFERS );
386 configAttribs.PushBack( 1 );
387 #endif // DALI_PROFILE_UBUNTU
388 configAttribs.PushBack( EGL_NONE );
390 if ( eglChooseConfig( mEglDisplay, &(configAttribs[0]), &mEglConfig, 1, &numConfigs ) != EGL_TRUE )
392 EGLint error = eglGetError();
395 case EGL_BAD_DISPLAY:
397 DALI_LOG_ERROR("Display is not an EGL display connection\n");
400 case EGL_BAD_ATTRIBUTE:
402 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");
405 case EGL_NOT_INITIALIZED:
407 DALI_LOG_ERROR("Display has not been initialized\n");
410 case EGL_BAD_PARAMETER:
412 DALI_LOG_ERROR("The parameter numConfig is NULL\n");
417 DALI_LOG_ERROR("Unknown error.\n");
420 DALI_ASSERT_ALWAYS(false && "eglChooseConfig failed!");
423 if ( numConfigs != 1 )
425 DALI_LOG_ERROR("No configurations found.\n");
427 TEST_EGL_ERROR("eglChooseConfig");
431 void EglImplementation::CreateSurfaceWindow( EGLNativeWindowType window, ColorDepth depth )
433 DALI_ASSERT_ALWAYS( ( mEglSurface == 0 ) && "EGL surface already exists" );
435 mEglNativeWindow = window;
440 ChooseConfig(mIsWindow, mColorDepth);
442 mEglSurface = eglCreateWindowSurface( mEglDisplay, mEglConfig, mEglNativeWindow, NULL );
443 TEST_EGL_ERROR("eglCreateWindowSurface");
445 DALI_ASSERT_ALWAYS( mEglSurface && "Create window surface failed" );
448 void EglImplementation::CreateSurfacePixmap( EGLNativePixmapType pixmap, ColorDepth depth )
450 DALI_ASSERT_ALWAYS( mEglSurface == 0 && "Cannot create more than one instance of surface pixmap" );
452 mEglNativePixmap = pixmap;
457 ChooseConfig(mIsWindow, mColorDepth);
459 mEglSurface = eglCreatePixmapSurface( mEglDisplay, mEglConfig, mEglNativePixmap, NULL );
460 TEST_EGL_ERROR("eglCreatePixmapSurface");
462 DALI_ASSERT_ALWAYS( mEglSurface && "Create pixmap surface failed" );
465 bool EglImplementation::ReplaceSurfaceWindow( EGLNativeWindowType window )
467 bool contextLost = false;
469 // display connection has not changed, then we can just create a new surface
470 // the surface is bound to the context, so set the context to null
473 // destroy the surface
476 // create the EGL surface
477 CreateSurfaceWindow( window, mColorDepth );
479 // set the context to be current with the new surface
480 MakeContextCurrent();
485 bool EglImplementation::ReplaceSurfacePixmap( EGLNativePixmapType pixmap )
487 bool contextLost = false;
489 // the surface is bound to the context, so set the context to null
492 // destroy the surface
495 // display connection has not changed, then we can just create a new surface
496 // create the EGL surface
497 CreateSurfacePixmap( pixmap, mColorDepth );
499 // set the context to be current with the new surface
500 MakeContextCurrent();
505 EGLDisplay EglImplementation::GetDisplay() const
510 EGLDisplay EglImplementation::GetContext() const
515 } // namespace Adaptor
517 } // namespace Internal