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