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