[Tizen] Add performance log
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles / egl-implementation.cpp
1 /*
2  * Copyright (c) 2023 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 // CLASS HEADER
19 #include <dali/internal/graphics/gles/egl-implementation.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23 #include <dali/integration-api/trace.h>
24 #include <dali/public-api/common/dali-vector.h>
25 #include <sstream>
26
27 // INTERNAL INCLUDES
28 #include <dali/devel-api/adaptor-framework/environment-variable.h>
29 #include <dali/internal/graphics/gles/egl-debug.h>
30 #include <dali/internal/graphics/gles/gl-implementation.h>
31 #include <dali/internal/system/common/time-service.h>
32 #include <dali/public-api/dali-adaptor-common.h>
33
34 // EGL constants use C style casts
35 #pragma GCC diagnostic push
36 #pragma GCC diagnostic ignored "-Wold-style-cast"
37
38 namespace
39 {
40 const uint32_t    THRESHOLD_SWAPBUFFER_COUNT              = 5;
41 const uint32_t    CHECK_EXTENSION_NUMBER                  = 4;
42 const uint32_t    EGL_VERSION_SUPPORT_SURFACELESS_CONTEXT = 15;
43 const std::string EGL_KHR_SURFACELESS_CONTEXT             = "EGL_KHR_surfaceless_context";
44 const std::string EGL_KHR_CREATE_CONTEXT                  = "EGL_KHR_create_context";
45 const std::string EGL_KHR_PARTIAL_UPDATE                  = "EGL_KHR_partial_update";
46 const std::string EGL_KHR_SWAP_BUFFERS_WITH_DAMAGE        = "EGL_KHR_swap_buffers_with_damage";
47
48 // Threshold time in miliseconds
49 constexpr auto PERFORMANCE_LOG_THRESHOLD_TIME_ENV = "DALI_EGL_PERFORMANCE_LOG_THRESHOLD_TIME";
50
51 DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_EGL, true);
52
53 uint32_t GetPerformanceLogThresholdTime()
54 {
55   auto     timeString = Dali::EnvironmentVariable::GetEnvironmentVariable(PERFORMANCE_LOG_THRESHOLD_TIME_ENV);
56   uint32_t time       = timeString ? static_cast<uint32_t>(std::atoi(timeString)) : 0u;
57   return time;
58 }
59 } // namespace
60
61 namespace Dali
62 {
63 namespace Internal
64 {
65 namespace Adaptor
66 {
67 #define TEST_EGL_ERROR(lastCommand)                        \
68   {                                                        \
69     EGLint err = eglGetError();                            \
70     if(err != EGL_SUCCESS)                                 \
71     {                                                      \
72       DALI_LOG_ERROR("EGL error after %s\n", lastCommand); \
73       Egl::PrintError(err);                                \
74       DALI_ASSERT_ALWAYS(0 && "EGL error");                \
75     }                                                      \
76   }
77
78 EglImplementation::EglImplementation(int                                 multiSamplingLevel,
79                                      Integration::DepthBufferAvailable   depthBufferRequired,
80                                      Integration::StencilBufferAvailable stencilBufferRequired,
81                                      Integration::PartialUpdateAvailable partialUpdateRequired)
82 : mContextAttribs(),
83   mEglNativeDisplay(0),
84   mEglNativeWindow(0),
85   mCurrentEglNativePixmap(0),
86   mEglDisplay(0),
87   mEglConfig(0),
88   mEglContext(0),
89   mCurrentEglSurface(0),
90   mCurrentEglContext(EGL_NO_CONTEXT),
91   mMultiSamplingLevel(multiSamplingLevel),
92   mGlesVersion(30),
93   mColorDepth(COLOR_DEPTH_24),
94   mGlesInitialized(false),
95   mIsOwnSurface(true),
96   mIsWindow(true),
97   mDepthBufferRequired(depthBufferRequired == Integration::DepthBufferAvailable::TRUE),
98   mStencilBufferRequired(stencilBufferRequired == Integration::StencilBufferAvailable::TRUE),
99   mPartialUpdateRequired(partialUpdateRequired == Integration::PartialUpdateAvailable::TRUE),
100   mIsSurfacelessContextSupported(false),
101   mIsKhrCreateContextSupported(false),
102   mSwapBufferCountAfterResume(0),
103   mEglSetDamageRegionKHR(0),
104   mEglSwapBuffersWithDamageKHR(0)
105 {
106 }
107
108 EglImplementation::~EglImplementation()
109 {
110   TerminateGles();
111 }
112
113 bool EglImplementation::InitializeGles(EGLNativeDisplayType display, bool isOwnSurface)
114 {
115   if(!mGlesInitialized)
116   {
117     mEglNativeDisplay = display;
118
119     // Try to get the display connection for the native display first
120     mEglDisplay = eglGetDisplay(mEglNativeDisplay);
121
122     if(mEglDisplay == EGL_NO_DISPLAY)
123     {
124       // If failed, try to get the default display connection
125       mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
126     }
127
128     if(mEglDisplay == EGL_NO_DISPLAY)
129     {
130       // Still failed to get a display connection
131       throw Dali::DaliException("", "OpenGL ES is not supported");
132     }
133
134     EGLint majorVersion = 0;
135     EGLint minorVersion = 0;
136     if(!eglInitialize(mEglDisplay, &majorVersion, &minorVersion))
137     {
138       return false;
139     }
140     eglBindAPI(EGL_OPENGL_ES_API);
141
142     mIsOwnSurface = isOwnSurface;
143   }
144
145   const char* const versionStr   = eglQueryString(mEglDisplay, EGL_VERSION);
146   const char* const extensionStr = eglQueryString(mEglDisplay, EGL_EXTENSIONS);
147
148   // Query EGL extensions to check whether required extensions are supported
149   std::istringstream versionStream(versionStr);
150   std::string        majorVersion, minorVersion;
151   std::getline(versionStream, majorVersion, '.');
152   std::getline(versionStream, minorVersion);
153   uint32_t extensionCheckCount = 0;
154   if(stoul(majorVersion) * 10 + stoul(minorVersion) >= EGL_VERSION_SUPPORT_SURFACELESS_CONTEXT)
155   {
156     mIsSurfacelessContextSupported = true;
157     mIsKhrCreateContextSupported   = true;
158     extensionCheckCount += 2;
159   }
160
161   std::istringstream stream(extensionStr);
162   std::string        currentExtension;
163   bool               isKhrPartialUpdateSupported         = false;
164   bool               isKhrSwapBuffersWithDamageSupported = false;
165   while(std::getline(stream, currentExtension, ' ') && extensionCheckCount < CHECK_EXTENSION_NUMBER)
166   {
167     if(currentExtension == EGL_KHR_SURFACELESS_CONTEXT && !mIsSurfacelessContextSupported)
168     {
169       mIsSurfacelessContextSupported = true;
170       extensionCheckCount++;
171     }
172     if(currentExtension == EGL_KHR_CREATE_CONTEXT && !mIsKhrCreateContextSupported)
173     {
174       mIsKhrCreateContextSupported = true;
175       extensionCheckCount++;
176     }
177     if(currentExtension == EGL_KHR_PARTIAL_UPDATE)
178     {
179       isKhrPartialUpdateSupported = true;
180       extensionCheckCount++;
181     }
182     if(currentExtension == EGL_KHR_SWAP_BUFFERS_WITH_DAMAGE)
183     {
184       isKhrSwapBuffersWithDamageSupported = true;
185       extensionCheckCount++;
186     }
187   }
188
189   if(!isKhrPartialUpdateSupported || !isKhrSwapBuffersWithDamageSupported)
190   {
191     mPartialUpdateRequired = false;
192   }
193
194   mGlesInitialized = true;
195
196   // We want to display this information all the time, so use the LogMessage directly
197   Integration::Log::LogMessage(Integration::Log::INFO,
198                                "EGL Information\n"
199                                "            PartialUpdate  %d\n"
200                                "            Vendor:        %s\n"
201                                "            Version:       %s\n"
202                                "            Client APIs:   %s\n"
203                                "            Extensions:    %s\n",
204                                mPartialUpdateRequired,
205                                eglQueryString(mEglDisplay, EGL_VENDOR),
206                                versionStr,
207                                eglQueryString(mEglDisplay, EGL_CLIENT_APIS),
208                                extensionStr);
209
210   return mGlesInitialized;
211 }
212
213 bool EglImplementation::CreateContext()
214 {
215   // make sure a context isn't created twice
216   DALI_ASSERT_ALWAYS((mEglContext == 0) && "EGL context recreated");
217
218   mEglContext = eglCreateContext(mEglDisplay, mEglConfig, NULL, &(mContextAttribs[0]));
219   TEST_EGL_ERROR("eglCreateContext render thread");
220
221   DALI_ASSERT_ALWAYS(EGL_NO_CONTEXT != mEglContext && "EGL context not created");
222
223   DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_VENDOR : %s ***\n", glGetString(GL_VENDOR));
224   DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_RENDERER : %s ***\n", glGetString(GL_RENDERER));
225   DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_VERSION : %s ***\n", glGetString(GL_VERSION));
226   DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_SHADING_LANGUAGE_VERSION : %s***\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
227   DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** Supported Extensions ***\n%s\n\n", glGetString(GL_EXTENSIONS));
228
229   mEglSetDamageRegionKHR = reinterpret_cast<PFNEGLSETDAMAGEREGIONKHRPROC>(eglGetProcAddress("eglSetDamageRegionKHR"));
230   if(!mEglSetDamageRegionKHR)
231   {
232     DALI_LOG_ERROR("Coudn't find eglSetDamageRegionKHR!\n");
233     mPartialUpdateRequired = false;
234   }
235   mEglSwapBuffersWithDamageKHR = reinterpret_cast<PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC>(eglGetProcAddress("eglSwapBuffersWithDamageKHR"));
236   if(!mEglSwapBuffersWithDamageKHR)
237   {
238     DALI_LOG_ERROR("Coudn't find eglSwapBuffersWithDamageKHR!\n");
239     mPartialUpdateRequired = false;
240   }
241   return true;
242 }
243
244 bool EglImplementation::CreateWindowContext(EGLContext& eglContext)
245 {
246   // make sure a context isn't created twice
247   DALI_ASSERT_ALWAYS((eglContext == 0) && "EGL context recreated");
248
249   eglContext = eglCreateContext(mEglDisplay, mEglConfig, mEglContext, &(mContextAttribs[0]));
250   TEST_EGL_ERROR("eglCreateContext render thread");
251
252   DALI_ASSERT_ALWAYS(EGL_NO_CONTEXT != eglContext && "EGL context not created");
253
254   DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_VENDOR : %s ***\n", glGetString(GL_VENDOR));
255   DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_RENDERER : %s ***\n", glGetString(GL_RENDERER));
256   DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_VERSION : %s ***\n", glGetString(GL_VERSION));
257   DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_SHADING_LANGUAGE_VERSION : %s***\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
258   DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** Supported Extensions ***\n%s\n\n", glGetString(GL_EXTENSIONS));
259
260   mEglWindowContexts.push_back(eglContext);
261
262   mEglSetDamageRegionKHR = reinterpret_cast<PFNEGLSETDAMAGEREGIONKHRPROC>(eglGetProcAddress("eglSetDamageRegionKHR"));
263   if(!mEglSetDamageRegionKHR)
264   {
265     DALI_LOG_ERROR("Coudn't find eglSetDamageRegionKHR!\n");
266     mPartialUpdateRequired = false;
267   }
268   mEglSwapBuffersWithDamageKHR = reinterpret_cast<PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC>(eglGetProcAddress("eglSwapBuffersWithDamageKHR"));
269   if(!mEglSwapBuffersWithDamageKHR)
270   {
271     DALI_LOG_ERROR("Coudn't find eglSwapBuffersWithDamageKHR!\n");
272     mPartialUpdateRequired = false;
273   }
274   return true;
275 }
276
277 void EglImplementation::DestroyContext(EGLContext& eglContext)
278 {
279   if(eglContext)
280   {
281     eglDestroyContext(mEglDisplay, eglContext);
282     eglContext = 0;
283   }
284 }
285
286 void EglImplementation::DestroySurface(EGLSurface& eglSurface)
287 {
288   if(mIsOwnSurface && eglSurface)
289   {
290     // Make context null to prevent crash in driver side
291     MakeContextNull();
292     eglDestroySurface(mEglDisplay, eglSurface);
293     eglSurface = 0;
294   }
295 }
296
297 void EglImplementation::MakeContextCurrent(EGLSurface eglSurface, EGLContext eglContext)
298 {
299   if(mCurrentEglContext == eglContext)
300   {
301     return;
302   }
303
304   mCurrentEglSurface = eglSurface;
305
306   if(mIsOwnSurface)
307   {
308     eglMakeCurrent(mEglDisplay, eglSurface, eglSurface, eglContext);
309
310     mCurrentEglContext = eglContext;
311   }
312
313   EGLint error = eglGetError();
314
315   if(error != EGL_SUCCESS)
316   {
317     Egl::PrintError(error);
318
319     DALI_ASSERT_ALWAYS(false && "MakeContextCurrent failed!");
320   }
321 }
322
323 void EglImplementation::MakeCurrent(EGLNativePixmapType pixmap, EGLSurface eglSurface)
324 {
325   if(mCurrentEglContext == mEglContext)
326   {
327     return;
328   }
329
330   mCurrentEglNativePixmap = pixmap;
331   mCurrentEglSurface      = eglSurface;
332
333   if(mIsOwnSurface)
334   {
335     eglMakeCurrent(mEglDisplay, eglSurface, eglSurface, mEglContext);
336
337     mCurrentEglContext = mEglContext;
338   }
339
340   EGLint error = eglGetError();
341
342   if(error != EGL_SUCCESS)
343   {
344     Egl::PrintError(error);
345
346     DALI_ASSERT_ALWAYS(false && "MakeCurrent failed!");
347   }
348 }
349
350 void EglImplementation::MakeContextNull()
351 {
352   // clear the current context
353   eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
354   mCurrentEglContext = EGL_NO_CONTEXT;
355 }
356
357 void EglImplementation::TerminateGles()
358 {
359   if(mGlesInitialized)
360   {
361     // Make context null to prevent crash in driver side
362     MakeContextNull();
363
364     for(auto eglSurface : mEglWindowSurfaces)
365     {
366       if(mIsOwnSurface && eglSurface)
367       {
368         eglDestroySurface(mEglDisplay, eglSurface);
369       }
370     }
371     eglDestroyContext(mEglDisplay, mEglContext);
372     for(auto eglContext : mEglWindowContexts)
373     {
374       eglDestroyContext(mEglDisplay, eglContext);
375     }
376
377     eglTerminate(mEglDisplay);
378
379     mEglDisplay        = NULL;
380     mEglConfig         = NULL;
381     mEglContext        = NULL;
382     mCurrentEglSurface = NULL;
383     mCurrentEglContext = EGL_NO_CONTEXT;
384
385     mGlesInitialized = false;
386   }
387 }
388
389 bool EglImplementation::IsGlesInitialized() const
390 {
391   return mGlesInitialized;
392 }
393
394 void EglImplementation::SwapBuffers(EGLSurface& eglSurface)
395 {
396   if(eglSurface != EGL_NO_SURFACE) // skip if using surfaceless context
397   {
398 #ifndef DALI_PROFILE_UBUNTU
399     if(mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT)
400     {
401       DALI_LOG_RELEASE_INFO("EglImplementation::eglSwapBuffers started. eglSurface(%p)\n", eglSurface);
402       DALI_TRACE_BEGIN(gTraceFilter, "DALI_EGL_SWAP_BUFFERS");
403     }
404 #endif //DALI_PROFILE_UBUNTU
405
406     // DALI_LOG_ERROR("EglImplementation::SwapBuffers()\n");
407     eglSwapBuffers(mEglDisplay, eglSurface);
408
409 #ifndef DALI_PROFILE_UBUNTU
410     if(mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT)
411     {
412       DALI_TRACE_END(gTraceFilter, "DALI_EGL_SWAP_BUFFERS");
413       DALI_LOG_RELEASE_INFO("EglImplementation::eglSwapBuffers finished.\n");
414       mSwapBufferCountAfterResume++;
415     }
416 #endif //DALI_PROFILE_UBUNTU
417   }
418 }
419
420 EGLint EglImplementation::GetBufferAge(EGLSurface& eglSurface) const
421 {
422   static uint32_t logThreshold = GetPerformanceLogThresholdTime();
423   static bool     logEnabled   = logThreshold > 0 ? true : false;
424
425   uint32_t startTime, endTime;
426   if(logEnabled)
427   {
428     startTime = TimeService::GetMilliSeconds();
429   }
430
431   EGLint age = 0;
432   eglQuerySurface(mEglDisplay, eglSurface, EGL_BUFFER_AGE_EXT, &age);
433   if(age < 0)
434   {
435     DALI_LOG_ERROR("eglQuerySurface(%d)\n", eglGetError());
436     age = 0;
437   }
438
439   if(logEnabled)
440   {
441     endTime = TimeService::GetMilliSeconds();
442     if(endTime - startTime > logThreshold)
443     {
444       DALI_LOG_DEBUG_INFO("eglQuerySurface takes long time! [%u ms]\n", endTime - startTime);
445     }
446   }
447   return age;
448 }
449
450 void EglImplementation::SetDamageRegion(EGLSurface& eglSurface, std::vector<Rect<int>>& damagedRects)
451 {
452   if(!mPartialUpdateRequired)
453   {
454     return;
455   }
456
457   if(eglSurface != EGL_NO_SURFACE) // skip if using surfaceless context
458   {
459     EGLBoolean result = mEglSetDamageRegionKHR(mEglDisplay, eglSurface, reinterpret_cast<int*>(damagedRects.data()), 1);
460     if(result == EGL_FALSE)
461     {
462       DALI_LOG_ERROR("eglSetDamageRegionKHR(0x%x)\n", eglGetError());
463     }
464   }
465 }
466
467 void EglImplementation::SwapBuffers(EGLSurface& eglSurface, const std::vector<Rect<int>>& damagedRects)
468 {
469   if(eglSurface != EGL_NO_SURFACE) // skip if using surfaceless context
470   {
471     if(!mPartialUpdateRequired)
472     {
473       SwapBuffers(eglSurface);
474       return;
475     }
476
477 #ifndef DALI_PROFILE_UBUNTU
478     if(mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT)
479     {
480       DALI_LOG_RELEASE_INFO("EglImplementation::eglSwapBuffersWithDamageKHR started. eglSurface(%p)\n", eglSurface);
481       DALI_TRACE_BEGIN(gTraceFilter, "DALI_EGL_SWAP_BUFFERS_KHR");
482     }
483 #endif //DALI_PROFILE_UBUNTU
484
485     EGLBoolean result = mEglSwapBuffersWithDamageKHR(mEglDisplay, eglSurface, reinterpret_cast<int*>(const_cast<std::vector<Rect<int>>&>(damagedRects).data()), damagedRects.size());
486     if(result == EGL_FALSE)
487     {
488       DALI_LOG_ERROR("eglSwapBuffersWithDamageKHR(%d)\n", eglGetError());
489     }
490
491 #ifndef DALI_PROFILE_UBUNTU
492     if(mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT)
493     {
494       DALI_TRACE_END(gTraceFilter, "DALI_EGL_SWAP_BUFFERS_KHR");
495       DALI_LOG_RELEASE_INFO("EglImplementation::eglSwapBuffersWithDamageKHR finished.\n");
496       mSwapBufferCountAfterResume++;
497     }
498 #endif //DALI_PROFILE_UBUNTU
499   }
500 }
501
502 void EglImplementation::CopyBuffers(EGLSurface& eglSurface)
503 {
504   eglCopyBuffers(mEglDisplay, eglSurface, mCurrentEglNativePixmap);
505 }
506
507 void EglImplementation::WaitGL()
508 {
509   eglWaitGL();
510 }
511
512 bool EglImplementation::ChooseConfig(bool isWindowType, ColorDepth depth)
513 {
514   if(mEglConfig && isWindowType == mIsWindow && mColorDepth == depth)
515   {
516     return true;
517   }
518
519   mColorDepth = depth;
520   mIsWindow   = isWindowType;
521
522   EGLint         numConfigs;
523   Vector<EGLint> configAttribs;
524   configAttribs.Reserve(31);
525
526   if(isWindowType)
527   {
528     configAttribs.PushBack(EGL_SURFACE_TYPE);
529     configAttribs.PushBack(EGL_WINDOW_BIT);
530   }
531   else
532   {
533     configAttribs.PushBack(EGL_SURFACE_TYPE);
534     configAttribs.PushBack(EGL_PIXMAP_BIT);
535   }
536
537   configAttribs.PushBack(EGL_RENDERABLE_TYPE);
538
539   if(mGlesVersion >= 30)
540   {
541     configAttribs.PushBack(EGL_OPENGL_ES3_BIT_KHR);
542   }
543   else
544   {
545     configAttribs.PushBack(EGL_OPENGL_ES2_BIT);
546   }
547
548   // TODO: enable this flag when it becomes supported
549   //  configAttribs.PushBack( EGL_CONTEXT_FLAGS_KHR );
550   //  configAttribs.PushBack( EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR );
551
552   configAttribs.PushBack(EGL_RED_SIZE);
553   configAttribs.PushBack(8);
554   configAttribs.PushBack(EGL_GREEN_SIZE);
555   configAttribs.PushBack(8);
556   configAttribs.PushBack(EGL_BLUE_SIZE);
557   configAttribs.PushBack(8);
558
559   //  For underlay video playback, we also need to set the alpha value of the 24/32bit window.
560   // TODO: When the tbm queue of GlView is 24bit, do we have to set the alpha size??
561   configAttribs.PushBack(EGL_ALPHA_SIZE);
562   configAttribs.PushBack(8);
563
564   configAttribs.PushBack(EGL_DEPTH_SIZE);
565   configAttribs.PushBack(mDepthBufferRequired ? 24 : 0);
566   configAttribs.PushBack(EGL_STENCIL_SIZE);
567   configAttribs.PushBack(mStencilBufferRequired ? 8 : 0);
568
569 #ifndef DALI_PROFILE_UBUNTU
570   if(mMultiSamplingLevel != EGL_DONT_CARE)
571   {
572     configAttribs.PushBack(EGL_SAMPLES);
573     configAttribs.PushBack(mMultiSamplingLevel);
574     configAttribs.PushBack(EGL_SAMPLE_BUFFERS);
575     configAttribs.PushBack(1);
576   }
577 #endif // DALI_PROFILE_UBUNTU
578   configAttribs.PushBack(EGL_NONE);
579
580   // Ensure number of configs is set to 1 as on some drivers,
581   // eglChooseConfig succeeds but does not actually create a proper configuration.
582   if((eglChooseConfig(mEglDisplay, &(configAttribs[0]), &mEglConfig, 1, &numConfigs) != EGL_TRUE) ||
583      (numConfigs != 1))
584   {
585     if(mGlesVersion >= 30)
586     {
587       mEglConfig = NULL;
588       DALI_LOG_ERROR("Fail to use OpenGL es 3.0. Retrying to use OpenGL es 2.0.");
589       return false;
590     }
591
592     if(numConfigs != 1)
593     {
594       DALI_LOG_ERROR("No configurations found.\n");
595
596       TEST_EGL_ERROR("eglChooseConfig");
597     }
598
599     EGLint error = eglGetError();
600     switch(error)
601     {
602       case EGL_BAD_DISPLAY:
603       {
604         DALI_LOG_ERROR("Display is not an EGL display connection\n");
605         break;
606       }
607       case EGL_BAD_ATTRIBUTE:
608       {
609         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");
610         break;
611       }
612       case EGL_NOT_INITIALIZED:
613       {
614         DALI_LOG_ERROR("Display has not been initialized\n");
615         break;
616       }
617       case EGL_BAD_PARAMETER:
618       {
619         DALI_LOG_ERROR("The parameter numConfig is NULL\n");
620         break;
621       }
622       default:
623       {
624         DALI_LOG_ERROR("Unknown error.\n");
625       }
626     }
627     DALI_ASSERT_ALWAYS(false && "eglChooseConfig failed!");
628     return false;
629   }
630   Integration::Log::LogMessage(Integration::Log::INFO, "Using OpenGL es %d.%d.\n", mGlesVersion / 10, mGlesVersion % 10);
631
632   mContextAttribs.Clear();
633   if(mIsKhrCreateContextSupported)
634   {
635     mContextAttribs.Reserve(5);
636     mContextAttribs.PushBack(EGL_CONTEXT_MAJOR_VERSION_KHR);
637     mContextAttribs.PushBack(mGlesVersion / 10);
638     mContextAttribs.PushBack(EGL_CONTEXT_MINOR_VERSION_KHR);
639     mContextAttribs.PushBack(mGlesVersion % 10);
640   }
641   else
642   {
643     mContextAttribs.Reserve(3);
644     mContextAttribs.PushBack(EGL_CONTEXT_CLIENT_VERSION);
645     mContextAttribs.PushBack(mGlesVersion / 10);
646   }
647   mContextAttribs.PushBack(EGL_NONE);
648
649   return true;
650 }
651
652 EGLSurface EglImplementation::CreateSurfaceWindow(EGLNativeWindowType window, ColorDepth depth)
653 {
654   mEglNativeWindow = window;
655   mColorDepth      = depth;
656   mIsWindow        = true;
657
658   // egl choose config
659   ChooseConfig(mIsWindow, mColorDepth);
660
661   mCurrentEglSurface = eglCreateWindowSurface(mEglDisplay, mEglConfig, mEglNativeWindow, NULL);
662   TEST_EGL_ERROR("eglCreateWindowSurface");
663
664   DALI_ASSERT_ALWAYS(mCurrentEglSurface && "Create window surface failed");
665
666   return mCurrentEglSurface;
667 }
668
669 EGLSurface EglImplementation::CreateSurfacePixmap(EGLNativePixmapType pixmap, ColorDepth depth)
670 {
671   mCurrentEglNativePixmap = pixmap;
672   mColorDepth             = depth;
673   mIsWindow               = false;
674
675   // egl choose config
676   ChooseConfig(mIsWindow, mColorDepth);
677
678   mCurrentEglSurface = eglCreatePixmapSurface(mEglDisplay, mEglConfig, mCurrentEglNativePixmap, NULL);
679   TEST_EGL_ERROR("eglCreatePixmapSurface");
680
681   DALI_ASSERT_ALWAYS(mCurrentEglSurface && "Create pixmap surface failed");
682
683   return mCurrentEglSurface;
684 }
685
686 bool EglImplementation::ReplaceSurfaceWindow(EGLNativeWindowType window, EGLSurface& eglSurface, EGLContext& eglContext)
687 {
688   bool contextLost = false;
689
690   // display connection has not changed, then we can just create a new surface
691   //  the surface is bound to the context, so set the context to null
692   MakeContextNull();
693
694   if(eglSurface)
695   {
696     // destroy the surface
697     DestroySurface(eglSurface);
698   }
699
700   // create the EGL surface
701   EGLSurface newEglSurface = CreateSurfaceWindow(window, mColorDepth);
702
703   // set the context to be current with the new surface
704   MakeContextCurrent(newEglSurface, eglContext);
705
706   return contextLost;
707 }
708
709 bool EglImplementation::ReplaceSurfacePixmap(EGLNativePixmapType pixmap, EGLSurface& eglSurface)
710 {
711   bool contextLost = false;
712
713   // display connection has not changed, then we can just create a new surface
714   // create the EGL surface
715   eglSurface = CreateSurfacePixmap(pixmap, mColorDepth);
716
717   // set the eglSurface to be current
718   MakeCurrent(pixmap, eglSurface);
719
720   return contextLost;
721 }
722
723 void EglImplementation::SetGlesVersion(const int32_t glesVersion)
724 {
725   mGlesVersion = glesVersion;
726 }
727
728 void EglImplementation::SetFirstFrameAfterResume()
729 {
730   mSwapBufferCountAfterResume = 0;
731 }
732
733 EGLDisplay EglImplementation::GetDisplay() const
734 {
735   return mEglDisplay;
736 }
737
738 EGLContext EglImplementation::GetContext() const
739 {
740   return mEglContext;
741 }
742
743 int32_t EglImplementation::GetGlesVersion() const
744 {
745   return mGlesVersion;
746 }
747
748 bool EglImplementation::IsSurfacelessContextSupported() const
749 {
750   return mIsSurfacelessContextSupported;
751 }
752
753 void EglImplementation::WaitClient()
754 {
755   // Wait for EGL to finish executing all rendering calls for the current context
756   if(eglWaitClient() != EGL_TRUE)
757   {
758     TEST_EGL_ERROR("eglWaitClient");
759   }
760 }
761
762 bool EglImplementation::IsPartialUpdateRequired() const
763 {
764   return mPartialUpdateRequired;
765 }
766
767 } // namespace Adaptor
768
769 } // namespace Internal
770
771 } // namespace Dali
772
773 #pragma GCC diagnostic pop