2 * Copyright (c) 2020 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 <dali/internal/graphics/gles/egl-implementation.h>
24 #include <dali/integration-api/debug.h>
25 #include <dali/public-api/common/dali-vector.h>
28 #include <dali/public-api/dali-adaptor-common.h>
29 #include <dali/internal/graphics/gles/gl-implementation.h>
30 #include <dali/internal/graphics/gles/egl-debug.h>
32 // EGL constants use C style casts
33 #pragma GCC diagnostic push
34 #pragma GCC diagnostic ignored "-Wold-style-cast"
38 const uint32_t THRESHOLD_SWAPBUFFER_COUNT = 5;
39 const uint32_t CHECK_EXTENSION_NUMBER = 2;
40 const std::string EGL_KHR_SURFACELESS_CONTEXT = "EGL_KHR_surfaceless_context";
41 const std::string EGL_KHR_CREATE_CONTEXT = "EGL_KHR_create_context";
53 #define TEST_EGL_ERROR(lastCommand) \
55 EGLint err = eglGetError(); \
56 if (err != EGL_SUCCESS) \
58 DALI_LOG_ERROR("EGL error after %s\n", lastCommand); \
59 Egl::PrintError(err); \
60 DALI_ASSERT_ALWAYS(0 && "EGL error"); \
64 EglImplementation::EglImplementation( int multiSamplingLevel,
65 Integration::DepthBufferAvailable depthBufferRequired,
66 Integration::StencilBufferAvailable stencilBufferRequired ,
67 Integration::PartialUpdateAvailable partialUpdateRequired )
69 mEglNativeDisplay( 0 ),
70 mEglNativeWindow( 0 ),
71 mCurrentEglNativePixmap( 0 ),
75 mCurrentEglSurface( 0 ),
76 mCurrentEglContext( EGL_NO_CONTEXT ),
77 mMultiSamplingLevel( multiSamplingLevel ),
79 mColorDepth( COLOR_DEPTH_24 ),
80 mGlesInitialized( false ),
81 mIsOwnSurface( true ),
83 mDepthBufferRequired( depthBufferRequired == Integration::DepthBufferAvailable::TRUE ),
84 mStencilBufferRequired( stencilBufferRequired == Integration::StencilBufferAvailable::TRUE ),
85 mPartialUpdateRequired( partialUpdateRequired == Integration::PartialUpdateAvailable::TRUE ),
86 mIsSurfacelessContextSupported( false ),
87 mIsKhrCreateContextSupported( false ),
88 mSwapBufferCountAfterResume( 0 ),
89 mEglSetDamageRegionKHR( 0 ),
90 mEglSwapBuffersWithDamageKHR( 0 ),
92 mFullSwapNextFrame( true )
96 EglImplementation::~EglImplementation()
101 bool EglImplementation::InitializeGles( EGLNativeDisplayType display, bool isOwnSurface )
103 if ( !mGlesInitialized )
105 mEglNativeDisplay = display;
107 // Try to get the display connection for the native display first
108 mEglDisplay = eglGetDisplay( mEglNativeDisplay );
110 if( mEglDisplay == EGL_NO_DISPLAY )
112 // If failed, try to get the default display connection
113 mEglDisplay = eglGetDisplay( EGL_DEFAULT_DISPLAY );
116 if( mEglDisplay == EGL_NO_DISPLAY )
118 // Still failed to get a display connection
119 throw Dali::DaliException( "", "OpenGL ES is not supported");
122 EGLint majorVersion = 0;
123 EGLint minorVersion = 0;
124 if ( !eglInitialize( mEglDisplay, &majorVersion, &minorVersion ) )
128 eglBindAPI(EGL_OPENGL_ES_API);
130 mIsOwnSurface = isOwnSurface;
133 // Query EGL extensions to check whether surfaceless context is supported
134 const char* const extensionStr = eglQueryString( mEglDisplay, EGL_EXTENSIONS );
135 std::istringstream stream( extensionStr );
136 std::string currentExtension;
137 uint32_t extensionCheckCount = 0;
138 while( std::getline( stream, currentExtension, ' ' ) && extensionCheckCount < CHECK_EXTENSION_NUMBER )
140 if( currentExtension == EGL_KHR_SURFACELESS_CONTEXT )
142 mIsSurfacelessContextSupported = true;
143 extensionCheckCount++;
145 if( currentExtension == EGL_KHR_CREATE_CONTEXT )
147 mIsKhrCreateContextSupported = true;
148 extensionCheckCount++;
152 mGlesInitialized = true;
154 // We want to display this information all the time, so use the LogMessage directly
155 Integration::Log::LogMessage(Integration::Log::DebugInfo, "EGL Information\n"
160 eglQueryString( mEglDisplay, EGL_VENDOR ),
161 eglQueryString( mEglDisplay, EGL_VERSION ),
162 eglQueryString( mEglDisplay, EGL_CLIENT_APIS ),
165 return mGlesInitialized;
168 bool EglImplementation::CreateContext()
170 // make sure a context isn't created twice
171 DALI_ASSERT_ALWAYS( (mEglContext == 0) && "EGL context recreated" );
173 mEglContext = eglCreateContext(mEglDisplay, mEglConfig, NULL, &(mContextAttribs[0]));
174 TEST_EGL_ERROR("eglCreateContext render thread");
176 DALI_ASSERT_ALWAYS( EGL_NO_CONTEXT != mEglContext && "EGL context not created" );
178 DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_VENDOR : %s ***\n", glGetString(GL_VENDOR));
179 DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_RENDERER : %s ***\n", glGetString(GL_RENDERER));
180 DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_VERSION : %s ***\n", glGetString(GL_VERSION));
181 DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_SHADING_LANGUAGE_VERSION : %s***\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
182 DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** Supported Extensions ***\n%s\n\n", glGetString(GL_EXTENSIONS));
184 mEglSetDamageRegionKHR = reinterpret_cast<PFNEGLSETDAMAGEREGIONKHRPROC>(eglGetProcAddress("eglSetDamageRegionKHR"));
185 if (!mEglSetDamageRegionKHR)
187 DALI_LOG_ERROR("Coudn't find eglSetDamageRegionKHR!\n");
188 mPartialUpdateRequired = false;
190 mEglSwapBuffersWithDamageKHR = reinterpret_cast<PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC>(eglGetProcAddress("eglSwapBuffersWithDamageKHR"));
191 if (!mEglSwapBuffersWithDamageKHR)
193 DALI_LOG_ERROR("Coudn't find eglSwapBuffersWithDamageKHR!\n");
194 mPartialUpdateRequired = false;
199 bool EglImplementation::CreateWindowContext( EGLContext& eglContext )
201 // make sure a context isn't created twice
202 DALI_ASSERT_ALWAYS( (eglContext == 0) && "EGL context recreated" );
204 eglContext = eglCreateContext(mEglDisplay, mEglConfig, mEglContext, &(mContextAttribs[0]));
205 TEST_EGL_ERROR("eglCreateContext render thread");
207 DALI_ASSERT_ALWAYS( EGL_NO_CONTEXT != eglContext && "EGL context not created" );
209 DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_VENDOR : %s ***\n", glGetString(GL_VENDOR));
210 DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_RENDERER : %s ***\n", glGetString(GL_RENDERER));
211 DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_VERSION : %s ***\n", glGetString(GL_VERSION));
212 DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_SHADING_LANGUAGE_VERSION : %s***\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
213 DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** Supported Extensions ***\n%s\n\n", glGetString(GL_EXTENSIONS));
215 mEglWindowContexts.push_back( eglContext );
217 mEglSetDamageRegionKHR = reinterpret_cast<PFNEGLSETDAMAGEREGIONKHRPROC>(eglGetProcAddress("eglSetDamageRegionKHR"));
218 if (!mEglSetDamageRegionKHR)
220 DALI_LOG_ERROR("Coudn't find eglSetDamageRegionKHR!\n");
221 mPartialUpdateRequired = false;
223 mEglSwapBuffersWithDamageKHR = reinterpret_cast<PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC>(eglGetProcAddress("eglSwapBuffersWithDamageKHR"));
224 if (!mEglSwapBuffersWithDamageKHR)
226 DALI_LOG_ERROR("Coudn't find eglSwapBuffersWithDamageKHR!\n");
227 mPartialUpdateRequired = false;
232 void EglImplementation::DestroyContext( EGLContext& eglContext )
236 eglDestroyContext( mEglDisplay, eglContext );
241 void EglImplementation::DestroySurface( EGLSurface& eglSurface )
243 if(mIsOwnSurface && eglSurface)
245 // Make context null to prevent crash in driver side
247 eglDestroySurface( mEglDisplay, eglSurface );
252 void EglImplementation::MakeContextCurrent( EGLSurface eglSurface, EGLContext eglContext )
254 if (mCurrentEglContext == eglContext)
259 mCurrentEglSurface = eglSurface;
263 eglMakeCurrent( mEglDisplay, eglSurface, eglSurface, eglContext );
265 mCurrentEglContext = eglContext;
268 EGLint error = eglGetError();
270 if ( error != EGL_SUCCESS )
272 Egl::PrintError(error);
274 DALI_ASSERT_ALWAYS(false && "MakeContextCurrent failed!");
278 void EglImplementation::MakeCurrent( EGLNativePixmapType pixmap, EGLSurface eglSurface )
280 if (mCurrentEglContext == mEglContext)
285 mCurrentEglNativePixmap = pixmap;
286 mCurrentEglSurface = eglSurface;
290 eglMakeCurrent( mEglDisplay, eglSurface, eglSurface, mEglContext );
292 mCurrentEglContext = mEglContext;
295 EGLint error = eglGetError();
297 if ( error != EGL_SUCCESS )
299 Egl::PrintError(error);
301 DALI_ASSERT_ALWAYS(false && "MakeCurrent failed!");
305 void EglImplementation::MakeContextNull()
307 // clear the current context
308 eglMakeCurrent( mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
309 mCurrentEglContext = EGL_NO_CONTEXT;
312 void EglImplementation::TerminateGles()
314 if ( mGlesInitialized )
316 // Make context null to prevent crash in driver side
319 for ( auto eglSurface : mEglWindowSurfaces )
321 if(mIsOwnSurface && eglSurface)
323 eglDestroySurface(mEglDisplay, eglSurface);
326 eglDestroyContext(mEglDisplay, mEglContext);
327 for ( auto eglContext : mEglWindowContexts )
329 eglDestroyContext(mEglDisplay, eglContext);
332 eglTerminate(mEglDisplay);
337 mCurrentEglSurface = NULL;
338 mCurrentEglContext = EGL_NO_CONTEXT;
340 mGlesInitialized = false;
344 bool EglImplementation::IsGlesInitialized() const
346 return mGlesInitialized;
349 void EglImplementation::SwapBuffers( EGLSurface& eglSurface )
351 if ( eglSurface != EGL_NO_SURFACE ) // skip if using surfaceless context
353 #ifndef DALI_PROFILE_UBUNTU
354 if( mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT )
356 DALI_LOG_RELEASE_INFO( "EglImplementation::SwapBuffers started.\n" );
358 #endif //DALI_PROFILE_UBUNTU
360 // DALI_LOG_ERROR("EglImplementation::SwapBuffers()\n");
361 eglSwapBuffers( mEglDisplay, eglSurface );
362 mFullSwapNextFrame = false;
364 #ifndef DALI_PROFILE_UBUNTU
365 if( mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT )
367 DALI_LOG_RELEASE_INFO( "EglImplementation::SwapBuffers finished.\n" );
368 mSwapBufferCountAfterResume++;
370 #endif //DALI_PROFILE_UBUNTU
374 EGLint EglImplementation::GetBufferAge(EGLSurface& eglSurface) const
377 eglQuerySurface(mEglDisplay, eglSurface, EGL_BUFFER_AGE_EXT, &age);
380 DALI_LOG_ERROR("eglQuerySurface(%d)\n", eglGetError());
384 // 0 - invalid buffer
388 DALI_LOG_ERROR("EglImplementation::GetBufferAge() buffer age %d > 3\n", age);
389 age = 0; // shoudn't be more than 3 back buffers, if there is just reset, I don't want to add extra history level
395 bool EglImplementation::DamageAreasSet() const
397 return (mDamagedAreas.size() ? true : false);
400 void EglImplementation::SetDamageAreas( std::vector<Dali::Rect<int>>& damagedAreas )
402 mFullSwapNextFrame = true;
403 mDamagedAreas = damagedAreas;
406 void EglImplementation::SetFullSwapNextFrame()
408 mFullSwapNextFrame = true;
411 void mergeRects(Rect<int>& mergingRect, const std::vector<Rect<int>>& rects)
414 if (mergingRect.IsEmpty())
416 for (;i < rects.size(); i++)
418 if (!rects[i].IsEmpty())
420 mergingRect = rects[i];
426 for (;i < rects.size(); i++)
428 mergingRect.Merge(rects[i]);
432 void insertRects(std::list<std::vector<Rect<int>>>& damagedRectsList, const std::vector<Rect<int>>& damagedRects)
434 damagedRectsList.push_front(damagedRects);
435 if (damagedRectsList.size() > 4) // past triple buffers + current
437 damagedRectsList.pop_back();
441 void EglImplementation::SetDamage( EGLSurface& eglSurface, const std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect )
443 if (!mPartialUpdateRequired)
448 if (eglSurface != EGL_NO_SURFACE) // skip if using surfaceless context
452 eglQuerySurface(mEglDisplay, eglSurface, EGL_WIDTH, &width);
453 eglQuerySurface(mEglDisplay, eglSurface, EGL_HEIGHT, &height);
454 Rect<int> surfaceRect(0, 0, width, height);
456 mSurfaceRect = surfaceRect;
458 if (mFullSwapNextFrame)
461 insertRects(mBufferDamagedRects, std::vector<Rect<int>>(1, surfaceRect));
462 clippingRect = Rect<int>();
466 EGLint bufferAge = GetBufferAge(eglSurface);
467 if (mDamagedAreas.size())
469 mBufferAge = bufferAge;
472 // Buffer age is reset
473 clippingRect = Rect<int>();
477 mergeRects(clippingRect, mDamagedAreas);
481 // Buffer age 0 means the back buffer in invalid and requires full swap
482 if (!damagedRects.size() || bufferAge != mBufferAge || bufferAge == 0)
484 // No damage or buffer is out of order or buffer age is reset
485 mBufferAge = bufferAge;
486 insertRects(mBufferDamagedRects, std::vector<Rect<int>>(1, surfaceRect));
487 clippingRect = Rect<int>();
491 // We push current frame damaged rects here, zero index for current frame
492 mBufferAge = bufferAge;
493 insertRects(mBufferDamagedRects, damagedRects);
495 // Merge damaged rects into clipping rect
496 auto bufferDamagedRects = mBufferDamagedRects.begin();
497 while (bufferAge-- >= 0 && bufferDamagedRects != mBufferDamagedRects.end())
499 const std::vector<Rect<int>>& rects = *bufferDamagedRects++;
500 mergeRects(clippingRect, rects);
504 if (!clippingRect.Intersect(surfaceRect) || clippingRect.Area() > surfaceRect.Area() * 0.8)
506 // clipping area too big or doesn't intersect surface rect
507 clippingRect = Rect<int>();
511 // DALI_LOG_ERROR("eglSetDamageRegionKHR(%d, %d, %d, %d)\n", clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height);
512 EGLBoolean result = mEglSetDamageRegionKHR(mEglDisplay, eglSurface, reinterpret_cast<int*>(&clippingRect), 1);
513 if (result == EGL_FALSE)
515 DALI_LOG_ERROR("eglSetDamageRegionKHR(%d)\n", eglGetError());
520 void EglImplementation::SwapBuffers(EGLSurface& eglSurface, const std::vector<Rect<int>>& damagedRects)
522 if (eglSurface != EGL_NO_SURFACE ) // skip if using surfaceless context
524 if (!mPartialUpdateRequired || mFullSwapNextFrame || mBufferAge == 0 || !damagedRects.size())
526 SwapBuffers(eglSurface);
530 #ifndef DALI_PROFILE_UBUNTU
531 if( mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT )
533 DALI_LOG_RELEASE_INFO( "EglImplementation::SwapBuffers started.\n" );
535 #endif //DALI_PROFILE_UBUNTU
537 if (mDamagedAreas.size())
539 // DALI_LOG_ERROR("EglImplementation::SwapBuffers(%d)\n", mDamagedAreas.size());
540 EGLBoolean result = mEglSwapBuffersWithDamageKHR(mEglDisplay, eglSurface, reinterpret_cast<int*>(mDamagedAreas.data()), mDamagedAreas.size());
541 if (result == EGL_FALSE)
543 DALI_LOG_ERROR("eglSwapBuffersWithDamageKHR(%d)\n", eglGetError());
546 #ifndef DALI_PROFILE_UBUNTU
547 if( mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT )
549 DALI_LOG_RELEASE_INFO( "EglImplementation::SwapBuffers finished.\n" );
550 mSwapBufferCountAfterResume++;
552 #endif //DALI_PROFILE_UBUNTU
556 // current frame damaged rects were pushed by EglImplementation::SetDamage() to 0 index.
557 EGLint bufferAge = mBufferAge;
558 mCombinedDamagedRects.clear();
560 // Combine damaged rects from previous frames (beginning from bufferAge index) with the current frame (0 index)
561 auto bufferDamagedRects = mBufferDamagedRects.begin();
562 while (bufferAge-- >= 0 && bufferDamagedRects != mBufferDamagedRects.end())
564 const std::vector<Rect<int>>& rects = *bufferDamagedRects++;
565 mCombinedDamagedRects.insert(mCombinedDamagedRects.end(), rects.begin(), rects.end());
568 // Merge intersecting rects, form an array of non intersecting rects to help driver a bit
569 // Could be optional and can be removed, needs to be checked with and without on platform
570 const int n = mCombinedDamagedRects.size();
571 for (int i = 0; i < n-1; i++)
573 if (mCombinedDamagedRects[i].IsEmpty())
578 for (int j = i+1; j < n; j++)
580 if (mCombinedDamagedRects[j].IsEmpty())
585 if (mCombinedDamagedRects[i].Intersects(mCombinedDamagedRects[j]))
587 mCombinedDamagedRects[i].Merge(mCombinedDamagedRects[j]);
588 mCombinedDamagedRects[j].width = 0;
589 mCombinedDamagedRects[j].height = 0;
595 for (int i = 0; i < n; i++)
597 if (!mCombinedDamagedRects[i].IsEmpty())
599 mCombinedDamagedRects[j++] = mCombinedDamagedRects[i];
605 mCombinedDamagedRects.resize(j);
608 if (!mCombinedDamagedRects.size() || (mCombinedDamagedRects[0].Area() > mSurfaceRect.Area() * 0.8))
610 SwapBuffers(eglSurface);
614 // DALI_LOG_ERROR("EglImplementation::SwapBuffers(%d)\n", mCombinedDamagedRects.size());
615 EGLBoolean result = mEglSwapBuffersWithDamageKHR(mEglDisplay, eglSurface, reinterpret_cast<int*>(mCombinedDamagedRects.data()), mCombinedDamagedRects.size());
616 if (result == EGL_FALSE)
618 DALI_LOG_ERROR("eglSwapBuffersWithDamageKHR(%d)\n", eglGetError());
621 #ifndef DALI_PROFILE_UBUNTU
622 if( mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT )
624 DALI_LOG_RELEASE_INFO( "EglImplementation::SwapBuffers finished.\n" );
625 mSwapBufferCountAfterResume++;
627 #endif //DALI_PROFILE_UBUNTU
631 void EglImplementation::CopyBuffers( EGLSurface& eglSurface )
633 eglCopyBuffers( mEglDisplay, eglSurface, mCurrentEglNativePixmap );
636 void EglImplementation::WaitGL()
641 bool EglImplementation::ChooseConfig( bool isWindowType, ColorDepth depth )
643 if(mEglConfig && isWindowType == mIsWindow && mColorDepth == depth)
649 mIsWindow = isWindowType;
652 Vector<EGLint> configAttribs;
653 configAttribs.Reserve(31);
657 configAttribs.PushBack( EGL_SURFACE_TYPE );
658 configAttribs.PushBack( EGL_WINDOW_BIT );
662 configAttribs.PushBack( EGL_SURFACE_TYPE );
663 configAttribs.PushBack( EGL_PIXMAP_BIT );
666 configAttribs.PushBack( EGL_RENDERABLE_TYPE );
668 if( mGlesVersion >= 30 )
670 configAttribs.PushBack( EGL_OPENGL_ES3_BIT_KHR );
674 configAttribs.PushBack( EGL_OPENGL_ES2_BIT );
677 // TODO: enable this flag when it becomes supported
678 // configAttribs.PushBack( EGL_CONTEXT_FLAGS_KHR );
679 // configAttribs.PushBack( EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR );
681 configAttribs.PushBack( EGL_RED_SIZE );
682 configAttribs.PushBack( 8 );
683 configAttribs.PushBack( EGL_GREEN_SIZE );
684 configAttribs.PushBack( 8 );
685 configAttribs.PushBack( EGL_BLUE_SIZE );
686 configAttribs.PushBack( 8 );
688 // For underlay video playback, we also need to set the alpha value of the 24/32bit window.
689 configAttribs.PushBack( EGL_ALPHA_SIZE );
690 configAttribs.PushBack( 8 );
692 configAttribs.PushBack( EGL_DEPTH_SIZE );
693 configAttribs.PushBack( mDepthBufferRequired ? 24 : 0 );
694 configAttribs.PushBack( EGL_STENCIL_SIZE );
695 configAttribs.PushBack( mStencilBufferRequired ? 8 : 0 );
697 #ifndef DALI_PROFILE_UBUNTU
698 if( mMultiSamplingLevel != EGL_DONT_CARE )
700 configAttribs.PushBack( EGL_SAMPLES );
701 configAttribs.PushBack( mMultiSamplingLevel );
702 configAttribs.PushBack( EGL_SAMPLE_BUFFERS );
703 configAttribs.PushBack( 1 );
705 #endif // DALI_PROFILE_UBUNTU
706 configAttribs.PushBack( EGL_NONE );
708 // Ensure number of configs is set to 1 as on some drivers,
709 // eglChooseConfig succeeds but does not actually create a proper configuration.
710 if ( ( eglChooseConfig( mEglDisplay, &(configAttribs[0]), &mEglConfig, 1, &numConfigs ) != EGL_TRUE ) ||
711 ( numConfigs != 1 ) )
713 if( mGlesVersion >= 30 )
716 DALI_LOG_ERROR("Fail to use OpenGL es 3.0. Retrying to use OpenGL es 2.0.");
720 if ( numConfigs != 1 )
722 DALI_LOG_ERROR("No configurations found.\n");
724 TEST_EGL_ERROR("eglChooseConfig");
727 EGLint error = eglGetError();
730 case EGL_BAD_DISPLAY:
732 DALI_LOG_ERROR("Display is not an EGL display connection\n");
735 case EGL_BAD_ATTRIBUTE:
737 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");
740 case EGL_NOT_INITIALIZED:
742 DALI_LOG_ERROR("Display has not been initialized\n");
745 case EGL_BAD_PARAMETER:
747 DALI_LOG_ERROR("The parameter numConfig is NULL\n");
752 DALI_LOG_ERROR("Unknown error.\n");
755 DALI_ASSERT_ALWAYS(false && "eglChooseConfig failed!");
758 Integration::Log::LogMessage(Integration::Log::DebugInfo, "Using OpenGL es %d.%d.\n", mGlesVersion / 10, mGlesVersion % 10 );
760 mContextAttribs.Clear();
761 if( mIsKhrCreateContextSupported )
763 mContextAttribs.Reserve(5);
764 mContextAttribs.PushBack( EGL_CONTEXT_MAJOR_VERSION_KHR );
765 mContextAttribs.PushBack( mGlesVersion / 10 );
766 mContextAttribs.PushBack( EGL_CONTEXT_MINOR_VERSION_KHR );
767 mContextAttribs.PushBack( mGlesVersion % 10 );
771 mContextAttribs.Reserve(3);
772 mContextAttribs.PushBack( EGL_CONTEXT_CLIENT_VERSION );
773 mContextAttribs.PushBack( mGlesVersion / 10 );
775 mContextAttribs.PushBack( EGL_NONE );
780 EGLSurface EglImplementation::CreateSurfaceWindow( EGLNativeWindowType window, ColorDepth depth )
782 mEglNativeWindow = window;
787 ChooseConfig(mIsWindow, mColorDepth);
789 mCurrentEglSurface = eglCreateWindowSurface( mEglDisplay, mEglConfig, mEglNativeWindow, NULL );
790 TEST_EGL_ERROR("eglCreateWindowSurface");
792 DALI_ASSERT_ALWAYS( mCurrentEglSurface && "Create window surface failed" );
794 return mCurrentEglSurface;
797 EGLSurface EglImplementation::CreateSurfacePixmap( EGLNativePixmapType pixmap, ColorDepth depth )
799 mCurrentEglNativePixmap = pixmap;
804 ChooseConfig(mIsWindow, mColorDepth);
806 mCurrentEglSurface = eglCreatePixmapSurface( mEglDisplay, mEglConfig, mCurrentEglNativePixmap, NULL );
807 TEST_EGL_ERROR("eglCreatePixmapSurface");
809 DALI_ASSERT_ALWAYS( mCurrentEglSurface && "Create pixmap surface failed" );
811 return mCurrentEglSurface;
814 bool EglImplementation::ReplaceSurfaceWindow( EGLNativeWindowType window, EGLSurface& eglSurface, EGLContext& eglContext )
816 bool contextLost = false;
818 // display connection has not changed, then we can just create a new surface
819 // the surface is bound to the context, so set the context to null
824 // destroy the surface
825 DestroySurface( eglSurface );
828 // create the EGL surface
829 EGLSurface newEglSurface = CreateSurfaceWindow( window, mColorDepth );
831 // set the context to be current with the new surface
832 MakeContextCurrent( newEglSurface, eglContext );
837 bool EglImplementation::ReplaceSurfacePixmap( EGLNativePixmapType pixmap, EGLSurface& eglSurface )
839 bool contextLost = false;
841 // display connection has not changed, then we can just create a new surface
842 // create the EGL surface
843 eglSurface = CreateSurfacePixmap( pixmap, mColorDepth );
845 // set the eglSurface to be current
846 MakeCurrent( pixmap, eglSurface );
851 void EglImplementation::SetGlesVersion( const int32_t glesVersion )
853 mGlesVersion = glesVersion;
856 void EglImplementation::SetFirstFrameAfterResume()
858 mSwapBufferCountAfterResume = 0;
861 EGLDisplay EglImplementation::GetDisplay() const
866 EGLContext EglImplementation::GetContext() const
871 int32_t EglImplementation::GetGlesVersion() const
876 bool EglImplementation::IsSurfacelessContextSupported() const
878 return mIsSurfacelessContextSupported;
881 void EglImplementation::WaitClient()
883 // Wait for EGL to finish executing all rendering calls for the current context
884 if ( eglWaitClient() != EGL_TRUE )
886 TEST_EGL_ERROR("eglWaitClient");
890 } // namespace Adaptor
892 } // namespace Internal
896 #pragma GCC diagnostic pop