Revert "Revert "WheelEvent class pimpling""
[platform/core/uifw/dali-adaptor.git] / dali / internal / window-system / common / gl-window-impl.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 // CLASS HEADER
19 #include <dali/internal/window-system/common/gl-window-impl.h>
20
21 // EXTERNAL HEADERS
22 #include <thread>
23 #include <dali/integration-api/core.h>
24 #include <dali/devel-api/adaptor-framework/orientation.h>
25 #include <dali/devel-api/adaptor-framework/gl-window.h>
26 #include <dali/integration-api/events/touch-integ.h>
27 #include <dali/integration-api/events/key-event-integ.h>
28
29 // INTERNAL HEADERS
30 //#include <dali/internal/graphics/gles/egl-graphics.h>
31 #include <dali/internal/window-system/common/event-handler.h>
32 #include <dali/internal/window-system/common/orientation-impl.h>
33 #include <dali/internal/window-system/common/window-factory.h>
34 #include <dali/internal/window-system/common/window-base.h>
35 #include <dali/internal/window-system/common/window-system.h>
36 #include <dali/internal/window-system/common/window-impl.h>
37 #include <dali/internal/window-system/common/window-render-surface.h>
38 #include <dali/internal/window-system/common/window-visibility-observer.h>
39 #include <dali/internal/graphics/gles/egl-graphics-factory.h>
40 #include <dali/internal/window-system/common/display-utils.h>
41
42 namespace Dali
43 {
44 namespace Internal
45 {
46 namespace Adaptor
47 {
48
49 namespace
50 {
51 const int MINIMUM_DIMENSION_CHANGE( 1 );
52
53 #if defined(DEBUG_ENABLED)
54 Debug::Filter* gWindowLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_WINDOW" );
55 #endif
56
57 } // unnamed namespace
58
59 GlWindow* GlWindow::New( const PositionSize& positionSize, const std::string& name, const std::string& className, bool isTransparent )
60 {
61   GlWindow* window = new GlWindow();
62   window->mIsTransparent = isTransparent;
63   window->Initialize( positionSize, name, className );
64   return window;
65 }
66
67 GlWindow::GlWindow()
68 : mWindowBase(),
69   mGraphics(),
70   mDisplayConnection( nullptr ),
71   mEventHandler( nullptr ),
72   mPositionSize(),
73   mColorDepth( COLOR_DEPTH_24 ),
74   mIsTransparent( false ),
75   mIsFocusAcceptable( false ),
76   mIconified( false ),
77   mOpaqueState( false ),
78   mResizedEnabled( false ),
79   mVisible( false ),
80   mIsRotated( false ),
81   mIsWindowRotated( false ),
82   mIsTouched( false ),
83   mAvailableAngles(),
84   mPreferredAngle( 0 ),
85   mTotalRotationAngle( 0 ),
86   mWindowRotationAngle( 0 ),
87   mScreenRotationAngle( 0 ),
88   mOrientationMode( 0 ),
89   mWindowWidth( 0 ),
90   mWindowHeight( 0 ),
91   mNativeWindowId( -1 ),
92   mKeyEventSignal(),
93   mTouchSignal(),
94   mFocusChangeSignal(),
95   mResizedSignal(),
96   mVisibilityChangedSignal(),
97   mGLRenderCallback( nullptr ),
98   mEGLSurface( nullptr ),
99   mEGLContext( nullptr ),
100   mGLESVersion( Dali::GlWindow::GlesVersion::VERSION_3_0 ),
101   mInitCallback( false ),
102   mDepth( false ),
103   mStencil( false ),
104   mIsEGLInitialize( false ),
105   mMSAA( 0 )
106 {
107 }
108
109 GlWindow::~GlWindow()
110 {
111   if ( mEventHandler )
112   {
113     mEventHandler->RemoveObserver( *this );
114   }
115
116   mGLTerminateCallback();
117
118   if( mIsEGLInitialize )
119   {
120     GraphicsInterface* graphics = mGraphics.get();
121     EglGraphics *eglGraphics = static_cast<EglGraphics*>( graphics );
122     Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
123
124     if( mEGLSurface )
125     {
126       eglImpl.DestroySurface( mEGLSurface );
127       mEGLSurface = nullptr;
128     }
129
130     if( mEGLContext )
131     {
132       eglImpl.DestroyContext( mEGLContext );
133       mEGLContext = nullptr;
134     }
135
136     eglImpl.TerminateGles();
137
138     mGraphics->Destroy();
139   }
140
141   delete mDisplayConnection;
142 }
143
144 void GlWindow::Initialize( const PositionSize& positionSize, const std::string& name, const std::string& className )
145 {
146   int screenWidth, screenHeight;
147
148   mPositionSize = positionSize;
149   WindowSystem::GetScreenSize( screenWidth, screenHeight );
150   if ( (mPositionSize.width == 0) || (mPositionSize.height == 0) )
151   {
152     mPositionSize.x = 0;
153     mPositionSize.y = 0;
154     mPositionSize.width = screenWidth;
155     mPositionSize.height = screenHeight;
156   }
157
158   if( screenWidth > screenHeight )
159   {
160     mOrientationMode = 1; // Default mode is landscape
161   }
162   else
163   {
164     mOrientationMode = 0; // Default mode is portrate
165   }
166
167   // Create a window base
168   auto windowFactory = Dali::Internal::Adaptor::GetWindowFactory();
169   Any surface;
170   mWindowBase = windowFactory->CreateWindowBase( mPositionSize, surface, ( mIsTransparent ? true : false ) );
171   mWindowBase->IconifyChangedSignal().Connect( this, &GlWindow::OnIconifyChanged );
172   mWindowBase->FocusChangedSignal().Connect( this, &GlWindow::OnFocusChanged );
173
174   SetEventHandler();
175
176   if( !mPositionSize.IsEmpty() )
177   {
178     AddAuxiliaryHint( "wm.policy.win.user.geometry", "1" );
179     mResizedEnabled = true;
180   }
181
182   mWindowBase->Show();
183
184   if( mIsTransparent )
185   {
186     mColorDepth = COLOR_DEPTH_32;
187   }
188   else
189   {
190     mColorDepth = COLOR_DEPTH_24;
191   }
192
193   SetClass( name, className );
194
195   // For Debugging
196   mNativeWindowId = mWindowBase->GetNativeWindowId();
197 }
198
199 void GlWindow::SetEventHandler()
200 {
201   mEventHandler = EventHandlerPtr( new EventHandler( mWindowBase.get(), *this ) );
202   mEventHandler->AddObserver( *this );
203 }
204
205 void GlWindow::SetClass( const std::string name, const std::string className )
206 {
207   mName = name;
208   mClassName = className;
209   mWindowBase->SetClass( name, className );
210 }
211
212 void GlWindow::SetEglConfig( bool depth, bool stencil, int msaa, Dali::GlWindow::GlesVersion version )
213 {
214   // Init Graphics
215   mDepth = depth;
216   mStencil = stencil;
217   mMSAA = msaa;
218   mGLESVersion = version;
219
220   InitializeGraphics();
221 }
222
223 void GlWindow::Raise()
224 {
225   mWindowBase->Raise();
226   DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Raise() \n", this, mNativeWindowId );
227 }
228
229 void GlWindow::Lower()
230 {
231   mWindowBase->Lower();
232   DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Lower() \n", this, mNativeWindowId );
233 }
234
235 void GlWindow::Activate()
236 {
237   mWindowBase->Activate();
238   DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Activate() \n", this, mNativeWindowId );
239 }
240
241 void GlWindow::Show()
242 {
243   mVisible = true;
244
245   mWindowBase->Show();
246
247   if( !mIconified )
248   {
249     Dali::GlWindow handle( this );
250     mVisibilityChangedSignal.Emit( handle, true );
251   }
252
253   if( mEventHandler )
254   {
255     mEventHandler->Resume();
256   }
257
258   DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Show(): iconified = %d, visible = %d\n", this, mNativeWindowId, mIconified, mVisible );
259 }
260
261 void GlWindow::Hide()
262 {
263   mVisible = false;
264
265   mWindowBase->Hide();
266
267   if( !mIconified )
268   {
269     Dali::GlWindow handle( this );
270     mVisibilityChangedSignal.Emit( handle, false );
271   }
272
273   if( mEventHandler )
274   {
275     mEventHandler->Pause();
276   }
277
278   DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Hide(): iconified = %d, visible = %d\n", this, mNativeWindowId, mIconified, mVisible );
279 }
280
281 unsigned int GlWindow::GetSupportedAuxiliaryHintCount() const
282 {
283   return mWindowBase->GetSupportedAuxiliaryHintCount();
284 }
285
286 std::string GlWindow::GetSupportedAuxiliaryHint( unsigned int index ) const
287 {
288   return mWindowBase->GetSupportedAuxiliaryHint( index );
289 }
290
291 unsigned int GlWindow::AddAuxiliaryHint( const std::string& hint, const std::string& value )
292 {
293   return mWindowBase->AddAuxiliaryHint( hint, value );
294 }
295
296 bool GlWindow::RemoveAuxiliaryHint( unsigned int id )
297 {
298   return mWindowBase->RemoveAuxiliaryHint( id );
299 }
300
301 bool GlWindow::SetAuxiliaryHintValue( unsigned int id, const std::string& value )
302 {
303   return mWindowBase->SetAuxiliaryHintValue( id, value );
304 }
305
306 std::string GlWindow::GetAuxiliaryHintValue( unsigned int id ) const
307 {
308   return mWindowBase->GetAuxiliaryHintValue( id );
309 }
310
311 unsigned int GlWindow::GetAuxiliaryHintId( const std::string& hint ) const
312 {
313   return mWindowBase->GetAuxiliaryHintId( hint );
314 }
315
316 void GlWindow::SetInputRegion( const Rect< int >& inputRegion )
317 {
318   mWindowBase->SetInputRegion( inputRegion );
319
320   DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "GlWindow::SetInputRegion: x = %d, y = %d, w = %d, h = %d\n", inputRegion.x, inputRegion.y, inputRegion.width, inputRegion.height );
321 }
322
323 void GlWindow::SetOpaqueState( bool opaque )
324 {
325   mOpaqueState = opaque;
326
327   mWindowBase->SetOpaqueState( opaque );
328
329   DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "GlWindow::SetOpaqueState: opaque = %d\n", opaque );
330 }
331
332 bool GlWindow::IsOpaqueState() const
333 {
334   return mOpaqueState;
335 }
336
337 void GlWindow::SetPositionSize( PositionSize positionSize )
338 {
339   if( !mResizedEnabled )
340   {
341     AddAuxiliaryHint( "wm.policy.win.user.geometry", "1" );
342     mResizedEnabled = true;
343   }
344
345   bool needToMove = false;
346   bool needToResize = false;
347
348   // Check moving
349   if( (fabs(positionSize.x - mPositionSize.x) > MINIMUM_DIMENSION_CHANGE) ||
350       (fabs(positionSize.y - mPositionSize.y) > MINIMUM_DIMENSION_CHANGE) )
351   {
352     needToMove = true;
353   }
354
355   // Check resizing
356   if( (fabs(positionSize.width - mPositionSize.width) > MINIMUM_DIMENSION_CHANGE) ||
357       (fabs(positionSize.height - mPositionSize.height) > MINIMUM_DIMENSION_CHANGE) )
358   {
359     needToResize = true;
360   }
361
362   if( needToResize )
363   {
364     if( needToMove )
365     {
366       mWindowBase->MoveResize( positionSize );
367     }
368     else
369     {
370       mWindowBase->Resize( positionSize );
371     }
372     mPositionSize = positionSize;
373   }
374   else
375   {
376     if( needToMove )
377     {
378       mWindowBase->Move( positionSize );
379       mPositionSize = positionSize;
380     }
381   }
382
383   // If window's size or position is changed, the signal will be emitted to user.
384   if( ( needToMove ) || ( needToResize ) )
385   {
386     Uint16Pair newSize( mPositionSize.width, mPositionSize.height );
387     mResizedSignal.Emit( newSize );
388   }
389 }
390
391 PositionSize GlWindow::GetPositionSize() const
392 {
393   PositionSize positionSize( mPositionSize );
394   if( mTotalRotationAngle == 90 || mTotalRotationAngle == 270 )
395   {
396     positionSize.height = mPositionSize.width;
397     positionSize.width = mPositionSize.height;
398   }
399
400   return positionSize;
401 }
402
403 void GlWindow::OnIconifyChanged( bool iconified )
404 {
405   if( iconified )
406   {
407     mIconified = true;
408
409     if( mVisible )
410     {
411       Dali::GlWindow handle( this );
412       mVisibilityChangedSignal.Emit( handle, false );
413     }
414
415     if( mEventHandler )
416     {
417       mEventHandler->Pause();
418     }
419
420     DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Iconified: visible = %d\n", this, mNativeWindowId, mVisible );
421   }
422   else
423   {
424     mIconified = false;
425
426     if( mVisible )
427     {
428       Dali::GlWindow handle( this );
429       mVisibilityChangedSignal.Emit( handle, true );
430     }
431
432     if( mEventHandler )
433     {
434       mEventHandler->Resume();
435     }
436
437     DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Deiconified: visible = %d\n", this, mNativeWindowId, mVisible );
438   }
439 }
440
441 void GlWindow::OnFocusChanged( bool focusIn )
442 {
443   Dali::GlWindow handle( this );
444   mFocusChangeSignal.Emit( handle, focusIn );
445 }
446
447 void GlWindow::OnOutputTransformed()
448 {
449   int screenRotationAngle = mWindowBase->GetScreenRotationAngle();
450   if( screenRotationAngle != mScreenRotationAngle )
451   {
452     mScreenRotationAngle = screenRotationAngle;
453     mTotalRotationAngle = (mWindowRotationAngle + mScreenRotationAngle) % 360;
454
455     if( mTotalRotationAngle == 90 || mTotalRotationAngle == 270 )
456     {
457       mWindowWidth = mPositionSize.height;
458       mWindowHeight = mPositionSize.width;
459     }
460     else
461     {
462       mWindowWidth = mPositionSize.width;
463       mWindowHeight = mPositionSize.height;
464     }
465
466     // Emit Resized signal
467     mResizedSignal.Emit( Dali::Uint16Pair( mWindowWidth, mWindowHeight ) );
468   }
469 }
470
471 void GlWindow::OnTouchPoint( Dali::Integration::Point& point, int timeStamp )
472 {
473   PointState::Type state = point.GetState();
474
475   if( state == PointState::DOWN )
476   {
477     mIsTouched = true;
478   }
479
480   if( state == PointState::UP )
481   {
482     mIsTouched = false;
483   }
484
485   if( !mIsTouched && state == PointState::MOTION )
486   {
487     return;
488   }
489
490   Dali::TouchEvent touchEvent = Dali::Integration::NewTouchEvent( timeStamp, point );
491   mTouchSignal.Emit( touchEvent );
492 }
493
494 void GlWindow::OnWheelEvent( Dali::Integration::WheelEvent& wheelEvent )
495 {
496   // TODO:
497   //FeedWheelEvent( wheelEvent );
498 }
499
500 void GlWindow::OnKeyEvent( Dali::Integration::KeyEvent& keyEvent )
501 {
502   Dali::KeyEvent event = Dali::Integration::KeyEvent::Convert( keyEvent );
503   mKeyEventSignal.Emit( event );
504 }
505
506 void GlWindow::OnRotation( const RotationEvent& rotation )
507 {
508   mWindowRotationAngle = rotation.angle;
509   mTotalRotationAngle = ( mWindowRotationAngle + mScreenRotationAngle ) % 360;
510   if( mTotalRotationAngle == 90 || mTotalRotationAngle == 270 )
511   {
512     mWindowWidth = mPositionSize.height;
513     mWindowHeight = mPositionSize.width;
514   }
515   else
516   {
517     mWindowWidth = mPositionSize.width;
518     mWindowHeight = mPositionSize.height;
519   }
520
521   mIsRotated = true;
522   mIsWindowRotated = true;
523   DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), OnRotation(): resized signal emit [%d x %d]\n", this, mNativeWindowId, mWindowWidth, mWindowHeight );
524
525   // Emit Resized signal
526   mResizedSignal.Emit( Dali::Uint16Pair( mWindowWidth, mWindowHeight ) );
527 }
528
529 void GlWindow::RecalculateTouchPosition( Integration::Point& point )
530 {
531   Vector2 position = point.GetScreenPosition();
532   Vector2 convertedPosition;
533
534   switch( mTotalRotationAngle )
535   {
536     case 90:
537     {
538       convertedPosition.x = static_cast<float>( mWindowWidth ) - position.y;
539       convertedPosition.y = position.x;
540       break;
541     }
542     case 180:
543     {
544       convertedPosition.x = static_cast<float>( mWindowWidth ) - position.x;
545       convertedPosition.y = static_cast<float>( mWindowHeight ) - position.y;
546       break;
547     }
548     case 270:
549     {
550       convertedPosition.x = position.y;
551       convertedPosition.y = static_cast<float>( mWindowHeight ) - position.x;
552       break;
553     }
554     default:
555     {
556       convertedPosition = position;
557       break;
558     }
559   }
560
561   point.SetScreenPosition( convertedPosition );
562 }
563
564 void GlWindow::SetAvailableAnlges( const std::vector< int >& angles )
565 {
566   if( angles.size() > 4 )
567   {
568     DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::SetAvailableAnlges: Invalid vector size! [%d]\n", angles.size() );
569     return;
570   }
571
572   mWindowBase->SetAvailableAnlges( angles );
573 }
574
575 bool GlWindow::IsOrientationAvailable( Dali::GlWindow::GlWindowOrientation orientation ) const
576 {
577   if( orientation <= Dali::GlWindow::GlWindowOrientation::NO_ORIENTATION_PREFERENCE
578       || orientation > Dali::GlWindow::GlWindowOrientation::LANDSCAPE_INVERSE )
579   {
580     DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::IsOrientationAvailable: Invalid input orientation [%d]\n", orientation );
581     return false;
582   }
583   return true;
584 }
585
586 int GlWindow::ConvertToAngle(  Dali::GlWindow::GlWindowOrientation  orientation )
587 {
588   int convertAngle = 0;
589   if ( mOrientationMode == 0 )
590   {
591     convertAngle = ( static_cast< int >( orientation ) ) * 90;
592   }
593   else if( mOrientationMode == 1)
594   {
595     switch( orientation )
596     {
597       case Dali::GlWindow::GlWindowOrientation::LANDSCAPE:
598       {
599         convertAngle = 0;
600         break;
601       }
602       case Dali::GlWindow::GlWindowOrientation::PORTRAIT:
603       {
604         convertAngle = 90;
605         break;
606       }
607       case Dali::GlWindow::GlWindowOrientation::LANDSCAPE_INVERSE:
608       {
609         convertAngle = 180;
610         break;
611       }
612       case Dali::GlWindow::GlWindowOrientation::PORTRAIT_INVERSE:
613       {
614         convertAngle = 270;
615         break;
616       }
617       case Dali::GlWindow::GlWindowOrientation::NO_ORIENTATION_PREFERENCE:
618       {
619         convertAngle = -1;
620         break;
621       }
622     }
623   }
624   return convertAngle;
625 }
626
627 Dali::GlWindow::GlWindowOrientation GlWindow::ConvertToOrientation( int angle ) const
628 {
629   Dali::GlWindow::GlWindowOrientation orientation = Dali::GlWindow::GlWindowOrientation::NO_ORIENTATION_PREFERENCE;
630   if ( mOrientationMode == 0 ) // Portrate mode
631   {
632     orientation = static_cast< Dali::GlWindow::GlWindowOrientation >( angle / 90 );
633   }
634   else if( mOrientationMode == 1 ) // Landscape mode
635   {
636     switch( angle )
637     {
638       case 0:
639       {
640         orientation = Dali::GlWindow::GlWindowOrientation::LANDSCAPE;
641         break;
642       }
643       case 90:
644       {
645         orientation = Dali::GlWindow::GlWindowOrientation::PORTRAIT;
646         break;
647       }
648       case 180:
649       {
650         orientation = Dali::GlWindow::GlWindowOrientation::LANDSCAPE_INVERSE;
651         break;
652       }
653       case 270:
654       {
655         orientation = Dali::GlWindow::GlWindowOrientation::PORTRAIT_INVERSE;
656         break;
657       }
658       case -1:
659       {
660         orientation = Dali::GlWindow::GlWindowOrientation::NO_ORIENTATION_PREFERENCE;
661         break;
662       }
663     }
664   }
665   return orientation;
666 }
667
668 Dali::GlWindow::GlWindowOrientation GlWindow::GetCurrentOrientation() const
669 {
670   DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), GetCurrentOrientation(): %d\n", this, mNativeWindowId, mTotalRotationAngle );
671   return ConvertToOrientation( mTotalRotationAngle );
672 }
673
674 void GlWindow::SetAvailableOrientations( const Dali::Vector< Dali::GlWindow::GlWindowOrientation >& orientations )
675 {
676   Dali::Vector<float>::SizeType count = orientations.Count();
677   for( Dali::Vector<float>::SizeType index = 0; index < count; ++index )
678   {
679     if( IsOrientationAvailable( orientations[index] ) == false )
680     {
681       DALI_LOG_ERROR("Window::SetAvailableRotationAngles, invalid angle: %d\n", orientations[index]);
682       continue;
683     }
684
685     bool found = false;
686     int angle = ConvertToAngle( orientations[index] );
687
688     for( std::size_t i = 0; i < mAvailableAngles.size(); i++ )
689     {
690       if( mAvailableAngles[i] == angle )
691       {
692         found = true;
693         break;
694       }
695     }
696
697     if( !found )
698     {
699       DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), SetAvailableOrientations: %d\n", this, mNativeWindowId, angle );
700       mAvailableAngles.push_back( angle );
701     }
702   }
703   SetAvailableAnlges( mAvailableAngles );
704 }
705
706 void GlWindow::SetPreferredOrientation( Dali::GlWindow::GlWindowOrientation orientation  )
707 {
708   if( IsOrientationAvailable( orientation ) == false )
709   {
710     DALI_LOG_ERROR( "Window::SetPreferredOrientation, invalid orientation: %d\n", orientation );
711     return;
712   }
713   mPreferredAngle = ConvertToAngle( orientation );
714   DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), SetPreferredOrientation: %d\n", this, mNativeWindowId, mPreferredAngle );
715   mWindowBase->SetPreferredAngle( mPreferredAngle );
716 }
717
718 void GlWindow::SetChild( Dali::Window& child )
719 {
720   if( DALI_UNLIKELY( child ) )
721   {
722     mChildWindow = child;
723     Internal::Adaptor::Window& windowImpl = Dali::GetImplementation( mChildWindow );
724     WindowRenderSurface* renderSurface = static_cast<WindowRenderSurface*>( windowImpl.GetSurface() );
725     WindowBase* childWindowBase = renderSurface->GetWindowBase();
726     childWindowBase->SetParent( mWindowBase.get() );
727   }
728 }
729
730 void GlWindow::RegisterGlCallback( GlInitialize glInit, GlRenderFrame glRenderFrame, GlTerminate glTerminate )
731 {
732   if( mIsEGLInitialize == false )
733   {
734     InitializeGraphics();
735   }
736   mGLInitCallback = glInit;
737   mGLRenderFrameCallback = glRenderFrame;
738   mGLTerminateCallback = glTerminate;
739
740   mInitCallback = false;
741
742   if( !mGLRenderCallback )
743   {
744     mGLRenderCallback = MakeCallback( this, &GlWindow::RunCallback );
745
746     Dali::Adaptor::Get().AddIdle( mGLRenderCallback, true );
747   }
748 }
749
750 bool GlWindow::RunCallback()
751 {
752   GraphicsInterface* graphics = mGraphics.get();
753   EglGraphics *eglGraphics = static_cast<EglGraphics*>( graphics );
754   Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
755
756   eglImpl.MakeContextCurrent( mEGLSurface, mEGLContext );
757
758   if( mIsRotated )
759   {
760     mWindowBase->SetEglWindowBufferTransform( mTotalRotationAngle );
761     if( mIsWindowRotated )
762     {
763       mWindowBase->SetEglWindowTransform( mWindowRotationAngle );
764     }
765     mIsRotated = false;
766   }
767
768   if( !mInitCallback )
769   {
770     mGLInitCallback();
771     mInitCallback = true;
772   }
773
774   mGLRenderFrameCallback();
775
776   if( mIsWindowRotated )
777   {
778     mWindowBase->WindowRotationCompleted( mWindowRotationAngle, mPositionSize.width, mPositionSize.height );
779     mIsWindowRotated = false;
780   }
781
782   eglImpl.SwapBuffers( mEGLSurface );
783
784   return true;
785 }
786
787 void GlWindow::RenderOnce()
788 {
789   RunCallback();
790 }
791
792 int32_t GlWindow::GetNativeId() const
793 {
794   return mWindowBase->GetNativeWindowId();
795 }
796
797 void GlWindow::InitializeGraphics()
798 {
799   if( !mIsEGLInitialize )
800   {
801     // Init Graphics
802     std::unique_ptr< GraphicsFactory > graphicsFactoryPtr = Utils::MakeUnique< GraphicsFactory >();
803     auto graphicsFactory = *graphicsFactoryPtr.get();
804
805     mGraphics = std::unique_ptr< GraphicsInterface >( &graphicsFactory.Create() );
806     GraphicsInterface* graphics = mGraphics.get();
807     EglGraphics *eglGraphics = static_cast<EglGraphics*>( graphics );
808     eglGraphics->Initialize( mDepth, mStencil, mMSAA );
809     eglGraphics->Create();
810
811     mDisplayConnection = Dali::DisplayConnection::New( *graphics, Dali::RenderSurfaceInterface::Type::WINDOW_RENDER_SURFACE );
812     mDisplayConnection->Initialize();
813
814     Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
815     if( mGLESVersion == Dali::GlWindow::GlesVersion::VERSION_2_0 )
816     {
817       eglImpl.SetGlesVersion( 20 );
818     }
819     else if( mGLESVersion == Dali::GlWindow::GlesVersion::VERSION_3_0 )
820     {
821       eglImpl.SetGlesVersion( 30 );
822     }
823
824     if( eglImpl.ChooseConfig(true, mColorDepth) == false )
825     {
826       if( mGLESVersion == Dali::GlWindow::GlesVersion::VERSION_3_0 )
827       {
828         DALI_LOG_RELEASE_INFO( "InitializeGraphics: Fail to choose config with GLES30, retry with GLES20\n" );
829         eglImpl.SetGlesVersion( 20 );
830         mGLESVersion = Dali::GlWindow::GlesVersion::VERSION_2_0;
831         if( eglImpl.ChooseConfig(true, mColorDepth) == false )
832         {
833           DALI_LOG_ERROR("InitializeGraphics: Fail to choose config with GLES20");
834           return;
835         }
836       }
837       else
838       {
839         DALI_LOG_ERROR("InitializeGraphics: Fail to choose config with GLES20");
840         return;
841       }
842     }
843     eglImpl.CreateWindowContext( mEGLContext );
844
845    // Create the EGL window
846     EGLNativeWindowType window = mWindowBase->CreateEglWindow( mPositionSize.width, mPositionSize.height );
847     mEGLSurface = eglImpl.CreateSurfaceWindow( window, mColorDepth );
848
849     mIsEGLInitialize = true;
850   }
851 }
852
853 void GlWindow::OnDamaged(  const DamageArea& area )
854 {
855
856 }
857
858 } // Adaptor
859
860 } // Internal
861
862 } // Dali