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