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 <wayland-egl.h>
21 #include <gl/egl-implementation.h>
24 #include <dali/integration-api/debug.h>
25 #include <dali/public-api/common/dali-common.h>
26 #include <dali/public-api/common/dali-vector.h>
29 #include <ecore-wl-render-surface.h>
40 #define TEST_EGL_ERROR(lastCommand) \
42 EGLint err = eglGetError(); \
43 if (err != EGL_SUCCESS) \
45 DALI_LOG_ERROR("EGL error after %s code=%d\n", lastCommand,err); \
46 DALI_ASSERT_ALWAYS(0 && "EGL error"); \
50 EglImplementation::EglImplementation()
51 : mEglNativeDisplay(0),
58 mGlesInitialized(false),
60 mContextCurrent(false),
62 mColorDepth(COLOR_DEPTH_24)
66 EglImplementation::~EglImplementation()
71 bool EglImplementation::InitializeGles( EGLNativeDisplayType display, bool isOwnSurface )
73 if ( !mGlesInitialized )
75 mEglNativeDisplay = display;
77 //@todo see if we can just EGL_DEFAULT_DISPLAY instead
78 mEglDisplay = eglGetDisplay(mEglNativeDisplay);
79 EGLint error = eglGetError();
81 if( mEglDisplay == NULL && error != EGL_SUCCESS )
83 throw Dali::DaliException( "", "OpenGL ES is not supported" );
86 EGLint majorVersion = 0;
87 EGLint minorVersion = 0;
88 if ( !eglInitialize( mEglDisplay, &majorVersion, &minorVersion ) )
92 eglBindAPI(EGL_OPENGL_ES_API);
94 mContextAttribs.Clear();
96 #if DALI_GLES_VERSION >= 30
98 mContextAttribs.Reserve(5);
99 mContextAttribs.PushBack( EGL_CONTEXT_MAJOR_VERSION_KHR );
100 mContextAttribs.PushBack( 3 );
101 mContextAttribs.PushBack( EGL_CONTEXT_MINOR_VERSION_KHR );
102 mContextAttribs.PushBack( 0 );
104 #else // DALI_GLES_VERSION >= 30
106 mContextAttribs.Reserve(3);
107 mContextAttribs.PushBack( EGL_CONTEXT_CLIENT_VERSION );
108 mContextAttribs.PushBack( 2 );
110 #endif // DALI_GLES_VERSION >= 30
112 mContextAttribs.PushBack( EGL_NONE );
114 mGlesInitialized = true;
115 mIsOwnSurface = isOwnSurface;
118 return mGlesInitialized;
121 bool EglImplementation::CreateContext()
123 // make sure a context isn't created twice
124 DALI_ASSERT_ALWAYS( (mEglContext == 0) && "EGL context recreated" );
126 mEglContext = eglCreateContext(mEglDisplay, mEglConfig, NULL, &(mContextAttribs[0]));
127 TEST_EGL_ERROR("eglCreateContext render thread");
129 DALI_ASSERT_ALWAYS( EGL_NO_CONTEXT != mEglContext && "EGL context not created" );
134 void EglImplementation::DestroyContext()
136 DALI_ASSERT_ALWAYS( mEglContext && "no EGL context" );
138 eglDestroyContext( mEglDisplay, mEglContext );
142 void EglImplementation::DestroySurface()
144 if(mIsOwnSurface && mEglSurface)
146 eglDestroySurface( mEglDisplay, mEglSurface );
151 void EglImplementation::MakeContextCurrent()
153 mContextCurrent = true;
157 eglMakeCurrent( mEglDisplay, mEglSurface, mEglSurface, mEglContext );
160 EGLint error = eglGetError();
162 if ( error != EGL_SUCCESS )
166 case EGL_BAD_DISPLAY:
168 DALI_LOG_ERROR("EGL_BAD_DISPLAY : Display is not an EGL display connection");
171 case EGL_NOT_INITIALIZED:
173 DALI_LOG_ERROR("EGL_NOT_INITIALIZED : Display has not been initialized");
176 case EGL_BAD_SURFACE:
178 DALI_LOG_ERROR("EGL_BAD_SURFACE : Draw or read is not an EGL surface");
181 case EGL_BAD_CONTEXT:
183 DALI_LOG_ERROR("EGL_BAD_CONTEXT : Context is not an EGL rendering context");
188 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");
193 DALI_LOG_ERROR("EGL_BAD_ACCESS : Context is current to some other thread");
196 case EGL_BAD_NATIVE_PIXMAP:
198 DALI_LOG_ERROR("EGL_BAD_NATIVE_PIXMAP : A native pixmap underlying either draw or read is no longer valid.");
201 case EGL_BAD_NATIVE_WINDOW:
203 DALI_LOG_ERROR("EGL_BAD_NATIVE_WINDOW : A native window underlying either draw or read is no longer valid.");
206 case EGL_BAD_CURRENT_SURFACE:
208 DALI_LOG_ERROR("EGL_BAD_CURRENT_SURFACE : The previous context has unflushed commands and the previous surface is no longer valid.");
213 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");
216 case EGL_CONTEXT_LOST:
218 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");
223 DALI_LOG_ERROR("Unknown error");
227 DALI_ASSERT_ALWAYS(false && "MakeContextCurrent failed!");
230 // We want to display this information all the time, so use the LogMessage directly
231 Integration::Log::LogMessage(Integration::Log::DebugInfo, "EGL Information\n"
236 eglQueryString(mEglDisplay, EGL_VENDOR),
237 eglQueryString(mEglDisplay, EGL_VERSION),
238 eglQueryString(mEglDisplay, EGL_CLIENT_APIS),
239 eglQueryString(mEglDisplay, EGL_EXTENSIONS));
242 void EglImplementation::MakeContextNull()
244 mContextCurrent = false;
245 // clear the current context
246 eglMakeCurrent( mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
249 void EglImplementation::TerminateGles()
251 if ( mGlesInitialized )
253 // in latest Mali DDK (r2p3 ~ r3p0 in April, 2012),
254 // MakeContextNull should be called before eglDestroy surface
255 // to prevent crash in _mali_surface_destroy_callback
258 if(mIsOwnSurface && mEglSurface)
260 eglDestroySurface(mEglDisplay, mEglSurface);
262 eglDestroyContext(mEglDisplay, mEglContext);
264 eglTerminate(mEglDisplay);
271 mGlesInitialized = false;
275 bool EglImplementation::IsGlesInitialized() const
277 return mGlesInitialized;
280 void EglImplementation::SwapBuffers()
282 eglSwapBuffers( mEglDisplay, mEglSurface );
285 void EglImplementation::CopyBuffers()
287 eglCopyBuffers( mEglDisplay, mEglSurface, mEglNativePixmap );
290 void EglImplementation::WaitGL()
295 void EglImplementation::ChooseConfig( bool isWindowType, ColorDepth depth )
297 if(mEglConfig && isWindowType == mIsWindow && mColorDepth == depth)
302 mIsWindow = isWindowType;
305 Vector<EGLint> configAttribs;
306 configAttribs.Reserve(31);
310 configAttribs.PushBack( EGL_SURFACE_TYPE );
311 configAttribs.PushBack( EGL_WINDOW_BIT );
315 configAttribs.PushBack( EGL_SURFACE_TYPE );
316 configAttribs.PushBack( EGL_PIXMAP_BIT );
319 configAttribs.PushBack( EGL_RENDERABLE_TYPE );
321 #if DALI_GLES_VERSION >= 30
324 configAttribs.PushBack( EGL_OPENGL_ES3_BIT_KHR );
326 // There is a bug in the desktop emulator
327 // Requesting for ES3 causes eglCreateContext even though it allows to ask
328 // for a configuration that supports GLES 3.0
329 configAttribs.PushBack( EGL_OPENGL_ES2_BIT );
332 #else // DALI_GLES_VERSION >= 30
334 configAttribs.PushBack( EGL_OPENGL_ES2_BIT );
336 #endif //DALI_GLES_VERSION >= 30
338 #if DALI_GLES_VERSION >= 30
339 // TODO: enable this flag when it becomes supported
340 // configAttribs.PushBack( EGL_CONTEXT_FLAGS_KHR );
341 // configAttribs.PushBack( EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR );
342 #endif //DALI_GLES_VERSION >= 30
344 configAttribs.PushBack( EGL_RED_SIZE );
345 configAttribs.PushBack( 8 );
346 configAttribs.PushBack( EGL_GREEN_SIZE );
347 configAttribs.PushBack( 8 );
348 configAttribs.PushBack( EGL_BLUE_SIZE );
349 configAttribs.PushBack( 8 );
351 configAttribs.PushBack( EGL_ALPHA_SIZE );
353 configAttribs.PushBack( (depth == COLOR_DEPTH_32) ? 8 : 0 );
355 // There is a bug in the desktop emulator
356 // setting EGL_ALPHA_SIZE to 8 results in eglChooseConfig failing
357 configAttribs.PushBack( 0 );
360 configAttribs.PushBack( EGL_DEPTH_SIZE );
361 configAttribs.PushBack( 24 );
362 configAttribs.PushBack( EGL_STENCIL_SIZE );
363 configAttribs.PushBack( 8 );
364 configAttribs.PushBack( EGL_SAMPLES );
365 configAttribs.PushBack( 4 );
366 configAttribs.PushBack( EGL_SAMPLE_BUFFERS );
367 configAttribs.PushBack( 1 );
368 configAttribs.PushBack( EGL_NONE );
370 if ( eglChooseConfig( mEglDisplay, &(configAttribs[0]), &mEglConfig, 1, &numConfigs ) != EGL_TRUE )
372 EGLint error = eglGetError();
375 case EGL_BAD_DISPLAY:
377 DALI_LOG_ERROR("Display is not an EGL display connection\n");
380 case EGL_BAD_ATTRIBUTE:
382 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");
385 case EGL_NOT_INITIALIZED:
387 DALI_LOG_ERROR("Display has not been initialized\n");
390 case EGL_BAD_PARAMETER:
392 DALI_LOG_ERROR("The parameter numConfig is NULL\n");
397 DALI_LOG_ERROR("Unknown error.\n");
400 DALI_ASSERT_ALWAYS(false && "eglChooseConfig failed!");
403 if ( numConfigs != 1 )
405 DALI_LOG_ERROR("No configurations found.\n");
407 TEST_EGL_ERROR("eglChooseConfig");
411 void EglImplementation::CreateSurfaceWindow( EGLNativeWindowType window, ColorDepth depth )
413 DALI_ASSERT_ALWAYS( ( mEglSurface == 0 ) && "EGL surface already exists" );
415 mEglNativeWindow = window;
420 ChooseConfig(mIsWindow, mColorDepth);
422 mEglSurface = eglCreateWindowSurface( mEglDisplay, mEglConfig, mEglNativeWindow, NULL );
423 TEST_EGL_ERROR("eglCreateWindowSurface");
425 DALI_ASSERT_ALWAYS( mEglSurface && "Create window surface failed" );
428 void EglImplementation::CreateSurfacePixmap( EGLNativePixmapType pixmap, ColorDepth depth )
430 DALI_ASSERT_ALWAYS( mEglSurface == 0 && "Cannot create more than one instance of surface pixmap" );
432 mEglNativePixmap = pixmap;
437 ChooseConfig(mIsWindow, mColorDepth);
439 mEglSurface = eglCreatePixmapSurface( mEglDisplay, mEglConfig, mEglNativePixmap, NULL );
440 TEST_EGL_ERROR("eglCreatePixmapSurface");
442 DALI_ASSERT_ALWAYS( mEglSurface && "Create pixmap surface failed" );
445 bool EglImplementation::ReplaceSurfaceWindow( EGLNativeWindowType window )
447 bool contextLost = false;
449 // display connection has not changed, then we can just create a new surface
450 // the surface is bound to the context, so set the context to null
453 // destroy the surface
456 // create the EGL surface
457 CreateSurfaceWindow( window, mColorDepth );
459 // set the context to be current with the new surface
460 MakeContextCurrent();
465 bool EglImplementation::ReplaceSurfacePixmap( EGLNativePixmapType pixmap )
467 bool contextLost = false;
469 // the surface is bound to the context, so set the context to null
472 // destroy the surface
475 // display connection has not changed, then we can just create a new surface
476 // create the EGL surface
477 CreateSurfacePixmap( pixmap, mColorDepth );
479 // set the context to be current with the new surface
480 MakeContextCurrent();
485 EGLDisplay EglImplementation::GetDisplay() const
490 EGLDisplay EglImplementation::GetContext() const
495 } // namespace Adaptor
497 } // namespace Internal