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