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