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