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