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