[Tizen] Fix build warning
[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 static 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   mLogThreshold = GetPerformanceLogThresholdTime();
195   mLogEnabled   = mLogThreshold > 0 ? true : false;
196
197   mGlesInitialized = true;
198
199   // We want to display this information all the time, so use the LogMessage directly
200   Integration::Log::LogMessage(Integration::Log::INFO,
201                                "EGL Information\n"
202                                "            PartialUpdate  %d\n"
203                                "            Vendor:        %s\n"
204                                "            Version:       %s\n"
205                                "            Client APIs:   %s\n"
206                                "            Extensions:    %s\n",
207                                mPartialUpdateRequired,
208                                eglQueryString(mEglDisplay, EGL_VENDOR),
209                                versionStr,
210                                eglQueryString(mEglDisplay, EGL_CLIENT_APIS),
211                                extensionStr);
212
213   return mGlesInitialized;
214 }
215
216 bool EglImplementation::CreateContext()
217 {
218   // make sure a context isn't created twice
219   DALI_ASSERT_ALWAYS((mEglContext == 0) && "EGL context recreated");
220
221   mEglContext = eglCreateContext(mEglDisplay, mEglConfig, NULL, &(mContextAttribs[0]));
222   TEST_EGL_ERROR("eglCreateContext render thread");
223
224   DALI_ASSERT_ALWAYS(EGL_NO_CONTEXT != mEglContext && "EGL context not created");
225
226   DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_VENDOR : %s ***\n", glGetString(GL_VENDOR));
227   DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_RENDERER : %s ***\n", glGetString(GL_RENDERER));
228   DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_VERSION : %s ***\n", glGetString(GL_VERSION));
229   DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_SHADING_LANGUAGE_VERSION : %s***\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
230   DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** Supported Extensions ***\n%s\n\n", glGetString(GL_EXTENSIONS));
231
232   mEglSetDamageRegionKHR = reinterpret_cast<PFNEGLSETDAMAGEREGIONKHRPROC>(eglGetProcAddress("eglSetDamageRegionKHR"));
233   if(!mEglSetDamageRegionKHR)
234   {
235     DALI_LOG_ERROR("Coudn't find eglSetDamageRegionKHR!\n");
236     mPartialUpdateRequired = false;
237   }
238   mEglSwapBuffersWithDamageKHR = reinterpret_cast<PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC>(eglGetProcAddress("eglSwapBuffersWithDamageKHR"));
239   if(!mEglSwapBuffersWithDamageKHR)
240   {
241     DALI_LOG_ERROR("Coudn't find eglSwapBuffersWithDamageKHR!\n");
242     mPartialUpdateRequired = false;
243   }
244   return true;
245 }
246
247 bool EglImplementation::CreateWindowContext(EGLContext& eglContext)
248 {
249   // make sure a context isn't created twice
250   DALI_ASSERT_ALWAYS((eglContext == 0) && "EGL context recreated");
251
252   eglContext = eglCreateContext(mEglDisplay, mEglConfig, mEglContext, &(mContextAttribs[0]));
253   TEST_EGL_ERROR("eglCreateContext render thread");
254
255   DALI_ASSERT_ALWAYS(EGL_NO_CONTEXT != eglContext && "EGL context not created");
256
257   DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_VENDOR : %s ***\n", glGetString(GL_VENDOR));
258   DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_RENDERER : %s ***\n", glGetString(GL_RENDERER));
259   DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_VERSION : %s ***\n", glGetString(GL_VERSION));
260   DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_SHADING_LANGUAGE_VERSION : %s***\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
261   DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** Supported Extensions ***\n%s\n\n", glGetString(GL_EXTENSIONS));
262
263   mEglWindowContexts.push_back(eglContext);
264
265   mEglSetDamageRegionKHR = reinterpret_cast<PFNEGLSETDAMAGEREGIONKHRPROC>(eglGetProcAddress("eglSetDamageRegionKHR"));
266   if(!mEglSetDamageRegionKHR)
267   {
268     DALI_LOG_ERROR("Coudn't find eglSetDamageRegionKHR!\n");
269     mPartialUpdateRequired = false;
270   }
271   mEglSwapBuffersWithDamageKHR = reinterpret_cast<PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC>(eglGetProcAddress("eglSwapBuffersWithDamageKHR"));
272   if(!mEglSwapBuffersWithDamageKHR)
273   {
274     DALI_LOG_ERROR("Coudn't find eglSwapBuffersWithDamageKHR!\n");
275     mPartialUpdateRequired = false;
276   }
277   return true;
278 }
279
280 void EglImplementation::DestroyContext(EGLContext& eglContext)
281 {
282   if(eglContext)
283   {
284     eglDestroyContext(mEglDisplay, eglContext);
285     eglContext = 0;
286   }
287 }
288
289 void EglImplementation::DestroySurface(EGLSurface& eglSurface)
290 {
291   if(mIsOwnSurface && eglSurface)
292   {
293     // Make context null to prevent crash in driver side
294     MakeContextNull();
295     eglDestroySurface(mEglDisplay, eglSurface);
296     eglSurface = 0;
297   }
298 }
299
300 void EglImplementation::MakeContextCurrent(EGLSurface eglSurface, EGLContext eglContext)
301 {
302   if(mCurrentEglContext == eglContext)
303   {
304     return;
305   }
306
307   mCurrentEglSurface = eglSurface;
308
309   if(mIsOwnSurface)
310   {
311     eglMakeCurrent(mEglDisplay, eglSurface, eglSurface, eglContext);
312
313     mCurrentEglContext = eglContext;
314   }
315
316   EGLint error = eglGetError();
317
318   if(error != EGL_SUCCESS)
319   {
320     Egl::PrintError(error);
321
322     DALI_ASSERT_ALWAYS(false && "MakeContextCurrent failed!");
323   }
324 }
325
326 void EglImplementation::MakeCurrent(EGLNativePixmapType pixmap, EGLSurface eglSurface)
327 {
328   if(mCurrentEglContext == mEglContext)
329   {
330     return;
331   }
332
333   mCurrentEglNativePixmap = pixmap;
334   mCurrentEglSurface      = eglSurface;
335
336   if(mIsOwnSurface)
337   {
338     eglMakeCurrent(mEglDisplay, eglSurface, eglSurface, mEglContext);
339
340     mCurrentEglContext = mEglContext;
341   }
342
343   EGLint error = eglGetError();
344
345   if(error != EGL_SUCCESS)
346   {
347     Egl::PrintError(error);
348
349     DALI_ASSERT_ALWAYS(false && "MakeCurrent failed!");
350   }
351 }
352
353 void EglImplementation::MakeContextNull()
354 {
355   // clear the current context
356   eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
357   mCurrentEglContext = EGL_NO_CONTEXT;
358 }
359
360 void EglImplementation::TerminateGles()
361 {
362   if(mGlesInitialized)
363   {
364     // Make context null to prevent crash in driver side
365     MakeContextNull();
366
367     for(auto eglSurface : mEglWindowSurfaces)
368     {
369       if(mIsOwnSurface && eglSurface)
370       {
371         eglDestroySurface(mEglDisplay, eglSurface);
372       }
373     }
374     eglDestroyContext(mEglDisplay, mEglContext);
375     for(auto eglContext : mEglWindowContexts)
376     {
377       eglDestroyContext(mEglDisplay, eglContext);
378     }
379
380     eglTerminate(mEglDisplay);
381
382     mEglDisplay        = NULL;
383     mEglConfig         = NULL;
384     mEglContext        = NULL;
385     mCurrentEglSurface = NULL;
386     mCurrentEglContext = EGL_NO_CONTEXT;
387
388     mGlesInitialized = false;
389   }
390 }
391
392 bool EglImplementation::IsGlesInitialized() const
393 {
394   return mGlesInitialized;
395 }
396
397 void EglImplementation::SwapBuffers(EGLSurface& eglSurface)
398 {
399   if(eglSurface != EGL_NO_SURFACE) // skip if using surfaceless context
400   {
401     uint32_t startTime = 0, endTime = 0;
402     if(mLogEnabled)
403     {
404       startTime = TimeService::GetMilliSeconds();
405     }
406
407 #ifndef DALI_PROFILE_UBUNTU
408     if(mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT)
409     {
410       DALI_LOG_RELEASE_INFO("EglImplementation::eglSwapBuffers started. eglSurface(%p)\n", eglSurface);
411       DALI_TRACE_BEGIN(gTraceFilter, "DALI_EGL_SWAP_BUFFERS");
412     }
413 #endif //DALI_PROFILE_UBUNTU
414
415     // DALI_LOG_ERROR("EglImplementation::SwapBuffers()\n");
416     eglSwapBuffers(mEglDisplay, eglSurface);
417
418 #ifndef DALI_PROFILE_UBUNTU
419     if(mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT)
420     {
421       DALI_TRACE_END(gTraceFilter, "DALI_EGL_SWAP_BUFFERS");
422       DALI_LOG_RELEASE_INFO("EglImplementation::eglSwapBuffers finished.\n");
423       mSwapBufferCountAfterResume++;
424     }
425 #endif //DALI_PROFILE_UBUNTU
426
427     if(mLogEnabled)
428     {
429       endTime = TimeService::GetMilliSeconds();
430       if(endTime - startTime > mLogThreshold)
431       {
432         DALI_LOG_DEBUG_INFO("eglSwapBuffers takes long time! [%u ms]\n", endTime - startTime);
433       }
434     }
435   }
436 }
437
438 EGLint EglImplementation::GetBufferAge(EGLSurface& eglSurface) const
439 {
440   uint32_t startTime = 0, endTime = 0;
441   if(mLogEnabled)
442   {
443     startTime = TimeService::GetMilliSeconds();
444   }
445
446   EGLint age = 0;
447   eglQuerySurface(mEglDisplay, eglSurface, EGL_BUFFER_AGE_EXT, &age);
448   if(age < 0)
449   {
450     DALI_LOG_ERROR("eglQuerySurface(%d)\n", eglGetError());
451     age = 0;
452   }
453
454   if(mLogEnabled)
455   {
456     endTime = TimeService::GetMilliSeconds();
457     if(endTime - startTime > mLogThreshold)
458     {
459       DALI_LOG_DEBUG_INFO("eglQuerySurface takes long time! [%u ms]\n", endTime - startTime);
460     }
461   }
462   return age;
463 }
464
465 void EglImplementation::SetDamageRegion(EGLSurface& eglSurface, std::vector<Rect<int>>& damagedRects)
466 {
467   if(!mPartialUpdateRequired)
468   {
469     return;
470   }
471
472   if(eglSurface != EGL_NO_SURFACE) // skip if using surfaceless context
473   {
474     EGLBoolean result = mEglSetDamageRegionKHR(mEglDisplay, eglSurface, reinterpret_cast<int*>(damagedRects.data()), 1);
475     if(result == EGL_FALSE)
476     {
477       DALI_LOG_ERROR("eglSetDamageRegionKHR(0x%x)\n", eglGetError());
478     }
479   }
480 }
481
482 void EglImplementation::SwapBuffers(EGLSurface& eglSurface, const std::vector<Rect<int>>& damagedRects)
483 {
484   if(eglSurface != EGL_NO_SURFACE) // skip if using surfaceless context
485   {
486     if(!mPartialUpdateRequired)
487     {
488       SwapBuffers(eglSurface);
489       return;
490     }
491
492     uint32_t startTime = 0, endTime = 0;
493     if(mLogEnabled)
494     {
495       startTime = TimeService::GetMilliSeconds();
496     }
497
498 #ifndef DALI_PROFILE_UBUNTU
499     if(mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT)
500     {
501       DALI_LOG_RELEASE_INFO("EglImplementation::eglSwapBuffersWithDamageKHR started. eglSurface(%p)\n", eglSurface);
502       DALI_TRACE_BEGIN(gTraceFilter, "DALI_EGL_SWAP_BUFFERS_KHR");
503     }
504 #endif //DALI_PROFILE_UBUNTU
505
506     EGLBoolean result = mEglSwapBuffersWithDamageKHR(mEglDisplay, eglSurface, reinterpret_cast<int*>(const_cast<std::vector<Rect<int>>&>(damagedRects).data()), damagedRects.size());
507     if(result == EGL_FALSE)
508     {
509       DALI_LOG_ERROR("eglSwapBuffersWithDamageKHR(%d)\n", eglGetError());
510     }
511
512 #ifndef DALI_PROFILE_UBUNTU
513     if(mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT)
514     {
515       DALI_TRACE_END(gTraceFilter, "DALI_EGL_SWAP_BUFFERS_KHR");
516       DALI_LOG_RELEASE_INFO("EglImplementation::eglSwapBuffersWithDamageKHR finished.\n");
517       mSwapBufferCountAfterResume++;
518     }
519 #endif //DALI_PROFILE_UBUNTU
520
521     if(mLogEnabled)
522     {
523       endTime = TimeService::GetMilliSeconds();
524       if(endTime - startTime > mLogThreshold)
525       {
526         DALI_LOG_DEBUG_INFO("eglSwapBuffersWithDamageKHR takes long time! [%u ms]\n", endTime - startTime);
527       }
528     }
529   }
530 }
531
532 void EglImplementation::CopyBuffers(EGLSurface& eglSurface)
533 {
534   eglCopyBuffers(mEglDisplay, eglSurface, mCurrentEglNativePixmap);
535 }
536
537 void EglImplementation::WaitGL()
538 {
539   eglWaitGL();
540 }
541
542 bool EglImplementation::ChooseConfig(bool isWindowType, ColorDepth depth)
543 {
544   if(mEglConfig && isWindowType == mIsWindow && mColorDepth == depth)
545   {
546     return true;
547   }
548
549   mColorDepth = depth;
550   mIsWindow   = isWindowType;
551
552   EGLint         numConfigs;
553   Vector<EGLint> configAttribs;
554   configAttribs.Reserve(31);
555
556   if(isWindowType)
557   {
558     configAttribs.PushBack(EGL_SURFACE_TYPE);
559     configAttribs.PushBack(EGL_WINDOW_BIT);
560   }
561   else
562   {
563     configAttribs.PushBack(EGL_SURFACE_TYPE);
564     configAttribs.PushBack(EGL_PIXMAP_BIT);
565   }
566
567   configAttribs.PushBack(EGL_RENDERABLE_TYPE);
568
569   if(mGlesVersion >= 30)
570   {
571     configAttribs.PushBack(EGL_OPENGL_ES3_BIT_KHR);
572   }
573   else
574   {
575     configAttribs.PushBack(EGL_OPENGL_ES2_BIT);
576   }
577
578   // TODO: enable this flag when it becomes supported
579   //  configAttribs.PushBack( EGL_CONTEXT_FLAGS_KHR );
580   //  configAttribs.PushBack( EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR );
581
582   configAttribs.PushBack(EGL_RED_SIZE);
583   configAttribs.PushBack(8);
584   configAttribs.PushBack(EGL_GREEN_SIZE);
585   configAttribs.PushBack(8);
586   configAttribs.PushBack(EGL_BLUE_SIZE);
587   configAttribs.PushBack(8);
588
589   //  For underlay video playback, we also need to set the alpha value of the 24/32bit window.
590   // TODO: When the tbm queue of GlView is 24bit, do we have to set the alpha size??
591   configAttribs.PushBack(EGL_ALPHA_SIZE);
592   configAttribs.PushBack(8);
593
594   configAttribs.PushBack(EGL_DEPTH_SIZE);
595   configAttribs.PushBack(mDepthBufferRequired ? 24 : 0);
596   configAttribs.PushBack(EGL_STENCIL_SIZE);
597   configAttribs.PushBack(mStencilBufferRequired ? 8 : 0);
598
599 #ifndef DALI_PROFILE_UBUNTU
600   if(mMultiSamplingLevel != EGL_DONT_CARE)
601   {
602     configAttribs.PushBack(EGL_SAMPLES);
603     configAttribs.PushBack(mMultiSamplingLevel);
604     configAttribs.PushBack(EGL_SAMPLE_BUFFERS);
605     configAttribs.PushBack(1);
606   }
607 #endif // DALI_PROFILE_UBUNTU
608   configAttribs.PushBack(EGL_NONE);
609
610   // Ensure number of configs is set to 1 as on some drivers,
611   // eglChooseConfig succeeds but does not actually create a proper configuration.
612   if((eglChooseConfig(mEglDisplay, &(configAttribs[0]), &mEglConfig, 1, &numConfigs) != EGL_TRUE) ||
613      (numConfigs != 1))
614   {
615     if(mGlesVersion >= 30)
616     {
617       mEglConfig = NULL;
618       DALI_LOG_ERROR("Fail to use OpenGL es 3.0. Retrying to use OpenGL es 2.0.");
619       return false;
620     }
621
622     if(numConfigs != 1)
623     {
624       DALI_LOG_ERROR("No configurations found.\n");
625
626       TEST_EGL_ERROR("eglChooseConfig");
627     }
628
629     EGLint error = eglGetError();
630     switch(error)
631     {
632       case EGL_BAD_DISPLAY:
633       {
634         DALI_LOG_ERROR("Display is not an EGL display connection\n");
635         break;
636       }
637       case EGL_BAD_ATTRIBUTE:
638       {
639         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");
640         break;
641       }
642       case EGL_NOT_INITIALIZED:
643       {
644         DALI_LOG_ERROR("Display has not been initialized\n");
645         break;
646       }
647       case EGL_BAD_PARAMETER:
648       {
649         DALI_LOG_ERROR("The parameter numConfig is NULL\n");
650         break;
651       }
652       default:
653       {
654         DALI_LOG_ERROR("Unknown error.\n");
655       }
656     }
657     DALI_ASSERT_ALWAYS(false && "eglChooseConfig failed!");
658     return false;
659   }
660   Integration::Log::LogMessage(Integration::Log::INFO, "Using OpenGL es %d.%d.\n", mGlesVersion / 10, mGlesVersion % 10);
661
662   mContextAttribs.Clear();
663   if(mIsKhrCreateContextSupported)
664   {
665     mContextAttribs.Reserve(5);
666     mContextAttribs.PushBack(EGL_CONTEXT_MAJOR_VERSION_KHR);
667     mContextAttribs.PushBack(mGlesVersion / 10);
668     mContextAttribs.PushBack(EGL_CONTEXT_MINOR_VERSION_KHR);
669     mContextAttribs.PushBack(mGlesVersion % 10);
670   }
671   else
672   {
673     mContextAttribs.Reserve(3);
674     mContextAttribs.PushBack(EGL_CONTEXT_CLIENT_VERSION);
675     mContextAttribs.PushBack(mGlesVersion / 10);
676   }
677   mContextAttribs.PushBack(EGL_NONE);
678
679   return true;
680 }
681
682 EGLSurface EglImplementation::CreateSurfaceWindow(EGLNativeWindowType window, ColorDepth depth)
683 {
684   mEglNativeWindow = window;
685   mColorDepth      = depth;
686   mIsWindow        = true;
687
688   // egl choose config
689   ChooseConfig(mIsWindow, mColorDepth);
690
691   mCurrentEglSurface = eglCreateWindowSurface(mEglDisplay, mEglConfig, mEglNativeWindow, NULL);
692   TEST_EGL_ERROR("eglCreateWindowSurface");
693
694   DALI_ASSERT_ALWAYS(mCurrentEglSurface && "Create window surface failed");
695
696   return mCurrentEglSurface;
697 }
698
699 EGLSurface EglImplementation::CreateSurfacePixmap(EGLNativePixmapType pixmap, ColorDepth depth)
700 {
701   mCurrentEglNativePixmap = pixmap;
702   mColorDepth             = depth;
703   mIsWindow               = false;
704
705   // egl choose config
706   ChooseConfig(mIsWindow, mColorDepth);
707
708   mCurrentEglSurface = eglCreatePixmapSurface(mEglDisplay, mEglConfig, mCurrentEglNativePixmap, NULL);
709   TEST_EGL_ERROR("eglCreatePixmapSurface");
710
711   DALI_ASSERT_ALWAYS(mCurrentEglSurface && "Create pixmap surface failed");
712
713   return mCurrentEglSurface;
714 }
715
716 bool EglImplementation::ReplaceSurfaceWindow(EGLNativeWindowType window, EGLSurface& eglSurface, EGLContext& eglContext)
717 {
718   bool contextLost = false;
719
720   // display connection has not changed, then we can just create a new surface
721   //  the surface is bound to the context, so set the context to null
722   MakeContextNull();
723
724   if(eglSurface)
725   {
726     // destroy the surface
727     DestroySurface(eglSurface);
728   }
729
730   // create the EGL surface
731   EGLSurface newEglSurface = CreateSurfaceWindow(window, mColorDepth);
732
733   // set the context to be current with the new surface
734   MakeContextCurrent(newEglSurface, eglContext);
735
736   return contextLost;
737 }
738
739 bool EglImplementation::ReplaceSurfacePixmap(EGLNativePixmapType pixmap, EGLSurface& eglSurface)
740 {
741   bool contextLost = false;
742
743   // display connection has not changed, then we can just create a new surface
744   // create the EGL surface
745   eglSurface = CreateSurfacePixmap(pixmap, mColorDepth);
746
747   // set the eglSurface to be current
748   MakeCurrent(pixmap, eglSurface);
749
750   return contextLost;
751 }
752
753 void EglImplementation::SetGlesVersion(const int32_t glesVersion)
754 {
755   mGlesVersion = glesVersion;
756 }
757
758 void EglImplementation::SetFirstFrameAfterResume()
759 {
760   mSwapBufferCountAfterResume = 0;
761 }
762
763 EGLDisplay EglImplementation::GetDisplay() const
764 {
765   return mEglDisplay;
766 }
767
768 EGLContext EglImplementation::GetContext() const
769 {
770   return mEglContext;
771 }
772
773 int32_t EglImplementation::GetGlesVersion() const
774 {
775   return mGlesVersion;
776 }
777
778 bool EglImplementation::IsSurfacelessContextSupported() const
779 {
780   return mIsSurfacelessContextSupported;
781 }
782
783 void EglImplementation::WaitClient()
784 {
785   // Wait for EGL to finish executing all rendering calls for the current context
786   if(eglWaitClient() != EGL_TRUE)
787   {
788     TEST_EGL_ERROR("eglWaitClient");
789   }
790 }
791
792 bool EglImplementation::IsPartialUpdateRequired() const
793 {
794   return mPartialUpdateRequired;
795 }
796
797 } // namespace Adaptor
798
799 } // namespace Internal
800
801 } // namespace Dali
802
803 #pragma GCC diagnostic pop