[Tizen] Remove list item in error case
[platform/core/uifw/dali-adaptor.git] / dali / internal / window-system / common / window-render-surface.cpp
index 45d147f..ed66eb5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -49,33 +49,102 @@ const float FULL_UPDATE_RATIO(0.8f);     ///< Force full update when the dirty a
 Debug::Filter* gWindowRenderSurfaceLogFilter = Debug::Filter::New(Debug::Verbose, false, "LOG_WINDOW_RENDER_SURFACE");
 #endif
 
-void MergeRects(Rect<int>& mergingRect, const std::vector<Rect<int>>& rects)
+void InsertRects(WindowRenderSurface::DamagedRectsContainer& damagedRectsList, const Rect<int>& damagedRects)
 {
-  uint32_t i = 0;
-  if(mergingRect.IsEmpty())
+  damagedRectsList.insert(damagedRectsList.begin(), damagedRects);
+  if(damagedRectsList.size() > 4) // past triple buffers + current
+  {
+    damagedRectsList.pop_back();
+  }
+}
+
+Rect<int32_t> RecalculateRect0(Rect<int32_t>& rect, const Rect<int32_t>& surfaceSize)
+{
+  return rect;
+}
+
+Rect<int32_t> RecalculateRect90(Rect<int32_t>& rect, const Rect<int32_t>& surfaceSize)
+{
+  Rect<int32_t> newRect;
+  newRect.x      = surfaceSize.height - (rect.y + rect.height);
+  newRect.y      = rect.x;
+  newRect.width  = rect.height;
+  newRect.height = rect.width;
+  return newRect;
+}
+
+Rect<int32_t> RecalculateRect180(Rect<int32_t>& rect, const Rect<int32_t>& surfaceSize)
+{
+  Rect<int32_t> newRect;
+  newRect.x      = surfaceSize.width - (rect.x + rect.width);
+  newRect.y      = surfaceSize.height - (rect.y + rect.height);
+  newRect.width  = rect.width;
+  newRect.height = rect.height;
+  return newRect;
+}
+
+Rect<int32_t> RecalculateRect270(Rect<int32_t>& rect, const Rect<int32_t>& surfaceSize)
+{
+  Rect<int32_t> newRect;
+  newRect.x      = rect.y;
+  newRect.y      = surfaceSize.width - (rect.x + rect.width);
+  newRect.width  = rect.height;
+  newRect.height = rect.width;
+  return newRect;
+}
+
+using RecalculateRectFunction = Rect<int32_t> (*)(Rect<int32_t>&, const Rect<int32_t>&);
+
+RecalculateRectFunction RecalculateRect[4] = {RecalculateRect0, RecalculateRect90, RecalculateRect180, RecalculateRect270};
+
+void MergeIntersectingRectsAndRotate(Rect<int>& mergingRect, std::vector<Rect<int>>& damagedRects, int orientation, const Rect<int32_t>& surfaceRect)
+{
+  const int n = damagedRects.size();
+  for(int i = 0; i < n - 1; i++)
   {
-    for(; i < rects.size(); i++)
+    if(damagedRects[i].IsEmpty())
+    {
+      continue;
+    }
+
+    for(int j = i + 1; j < n; j++)
     {
-      if(!rects[i].IsEmpty())
+      if(damagedRects[j].IsEmpty())
       {
-        mergingRect = rects[i];
-        break;
+        continue;
+      }
+
+      if(damagedRects[i].Intersects(damagedRects[j]))
+      {
+        damagedRects[i].Merge(damagedRects[j]);
+        damagedRects[j].width  = 0;
+        damagedRects[j].height = 0;
       }
     }
   }
 
-  for(; i < rects.size(); i++)
+  int j = 0;
+  for(int i = 0; i < n; i++)
   {
-    mergingRect.Merge(rects[i]);
+    if(!damagedRects[i].IsEmpty())
+    {
+      // Merge rects before rotate
+      if(mergingRect.IsEmpty())
+      {
+        mergingRect = damagedRects[i];
+      }
+      else
+      {
+        mergingRect.Merge(damagedRects[i]);
+      }
+
+      damagedRects[j++] = RecalculateRect[orientation](damagedRects[i], surfaceRect);
+    }
   }
-}
 
-void InsertRects(WindowRenderSurface::DamagedRectsContainer& damagedRectsList, const std::vector<Rect<int>>& damagedRects)
-{
-  damagedRectsList.push_front(damagedRects);
-  if(damagedRectsList.size() > 4) // past triple buffers + current
+  if(j != 0)
   {
-    damagedRectsList.pop_back();
+    damagedRects.resize(j);
   }
 }
 
@@ -88,13 +157,14 @@ WindowRenderSurface::WindowRenderSurface(Dali::PositionSize positionSize, Any su
   mWindowBase(),
   mThreadSynchronization(nullptr),
   mRenderNotification(nullptr),
-  mRotationTrigger(nullptr),
+  mPostRenderTrigger(),
   mFrameRenderedTrigger(),
   mGraphics(nullptr),
   mEGLSurface(nullptr),
   mEGLContext(nullptr),
   mColorDepth(isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24),
   mOutputTransformedSignal(),
+  mWindowRotationFinishedSignal(),
   mFrameCallbackInfoContainer(),
   mBufferDamagedRects(),
   mMutex(),
@@ -103,10 +173,9 @@ WindowRenderSurface::WindowRenderSurface(Dali::PositionSize positionSize, Any su
   mDpiHorizontal(0),
   mDpiVertical(0),
   mOwnSurface(false),
-  mWindowRotationFinished(true),
-  mScreenRotationFinished(true),
-  mResizeFinished(true),
-  mDefaultScreenRotationAvailable(false)
+  mIsImeWindowSurface(false),
+  mNeedWindowRotationAcknowledgement(false),
+  mIsWindowOrientationChanging(false)
 {
   DALI_LOG_INFO(gWindowRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n");
   Initialize(surface);
@@ -114,10 +183,6 @@ WindowRenderSurface::WindowRenderSurface(Dali::PositionSize positionSize, Any su
 
 WindowRenderSurface::~WindowRenderSurface()
 {
-  if(mRotationTrigger)
-  {
-    delete mRotationTrigger;
-  }
 }
 
 void WindowRenderSurface::Initialize(Any surface)
@@ -139,13 +204,11 @@ void WindowRenderSurface::Initialize(Any surface)
   mWindowBase->OutputTransformedSignal().Connect(this, &WindowRenderSurface::OutputTransformed);
 
   // Check screen rotation
-  mScreenRotationAngle = mWindowBase->GetScreenRotationAngle();
-  if(mScreenRotationAngle != 0)
+  int screenRotationAngle = mWindowBase->GetScreenRotationAngle();
+  if(screenRotationAngle != 0)
   {
-    mScreenRotationFinished         = false;
-    mResizeFinished                 = false;
-    mDefaultScreenRotationAvailable = true;
-    DALI_LOG_RELEASE_INFO("WindowRenderSurface::Initialize, screen rotation is enabled, screen rotation angle:[%d]\n", mScreenRotationAngle);
+    OutputTransformed();
+    DALI_LOG_RELEASE_INFO("WindowRenderSurface::Initialize, screen rotation is enabled, screen rotation angle:[%d]\n", screenRotationAngle);
   }
 }
 
@@ -174,22 +237,20 @@ void WindowRenderSurface::SetTransparency(bool transparent)
   mWindowBase->SetTransparency(transparent);
 }
 
-void WindowRenderSurface::RequestRotation(int angle, int width, int height)
+void WindowRenderSurface::RequestRotation(int angle, PositionSize positionSize)
 {
-  if(!mRotationTrigger)
+  if(!mPostRenderTrigger)
   {
-    mRotationTrigger = TriggerEventFactory::CreateTriggerEvent(MakeCallback(this, &WindowRenderSurface::ProcessRotationRequest), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
+    mPostRenderTrigger = std::unique_ptr<TriggerEventInterface>(TriggerEventFactory::CreateTriggerEvent(MakeCallback(this, &WindowRenderSurface::ProcessPostRender),
+                                                                                                        TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER));
   }
 
-  mPositionSize.width  = width;
-  mPositionSize.height = height;
-
-  mWindowRotationAngle    = angle;
-  mWindowRotationFinished = false;
+  mPositionSize.x = positionSize.x;
+  mPositionSize.y = positionSize.y;
 
-  mWindowBase->SetWindowRotationAngle(mWindowRotationAngle);
+  mWindowBase->SetWindowRotationAngle(angle);
 
-  DALI_LOG_INFO(gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: angle = %d screen rotation = %d\n", mWindowRotationAngle, mScreenRotationAngle);
+  DALI_LOG_RELEASE_INFO("start window rotation angle = %d screen rotation = %d\n", angle, mScreenRotationAngle);
 }
 
 WindowBase* WindowRenderSurface::GetWindowBase()
@@ -202,6 +263,11 @@ WindowBase::OutputSignalType& WindowRenderSurface::OutputTransformedSignal()
   return mOutputTransformedSignal;
 }
 
+WindowRenderSurface::RotationFinishedSignalType& WindowRenderSurface::RotationFinishedSignal()
+{
+  return mWindowRotationFinishedSignal;
+}
+
 PositionSize WindowRenderSurface::GetPositionSize() const
 {
   return mPositionSize;
@@ -227,22 +293,27 @@ void WindowRenderSurface::GetDpi(unsigned int& dpiHorizontal, unsigned int& dpiV
   dpiVertical   = mDpiVertical;
 }
 
-int WindowRenderSurface::GetOrientation() const
+int WindowRenderSurface::GetSurfaceOrientation() const
 {
-  return mWindowBase->GetOrientation();
+  return mWindowBase->GetWindowRotationAngle();
+}
+
+int WindowRenderSurface::GetScreenOrientation() const
+{
+  return mWindowBase->GetScreenRotationAngle();
 }
 
 void WindowRenderSurface::InitializeGraphics()
 {
-  mGraphics = &mAdaptor->GetGraphicsInterface();
+  if(mEGLContext == NULL)
+  {
+    mGraphics = &mAdaptor->GetGraphicsInterface();
 
-  DALI_ASSERT_ALWAYS(mGraphics && "Graphics interface is not created");
+    DALI_ASSERT_ALWAYS(mGraphics && "Graphics interface is not created");
 
-  auto eglGraphics = static_cast<EglGraphics*>(mGraphics);
-  mEGL             = &eglGraphics->GetEglInterface();
+    auto eglGraphics = static_cast<EglGraphics*>(mGraphics);
+    mEGL             = &eglGraphics->GetEglInterface();
 
-  if(mEGLContext == NULL)
-  {
     // Create the OpenGL context for this window
     Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>(*mEGL);
     eglImpl.ChooseConfig(true, mColorDepth);
@@ -277,8 +348,9 @@ void WindowRenderSurface::CreateSurface()
   Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
   mEGLSurface                                   = eglImpl.CreateSurfaceWindow(window, mColorDepth);
 
-  DALI_LOG_RELEASE_INFO("WindowRenderSurface::CreateSurface: WinId (%d), w = %d h = %d angle = %d screen rotation = %d\n",
+  DALI_LOG_RELEASE_INFO("WindowRenderSurface::CreateSurface: WinId (%d), EGLSurface (%p), w = %d h = %d angle = %d screen rotation = %d\n",
                         mWindowBase->GetNativeWindowId(),
+                        mEGLSurface,
                         mPositionSize.width,
                         mPositionSize.height,
                         mWindowRotationAngle,
@@ -329,59 +401,33 @@ bool WindowRenderSurface::ReplaceGraphicsSurface()
   // Create the EGL window
   EGLNativeWindowType window = mWindowBase->CreateEglWindow(width, height);
 
-  // Set screen rotation
-  mScreenRotationFinished = false;
-
   auto eglGraphics = static_cast<EglGraphics*>(mGraphics);
 
   Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
   return eglImpl.ReplaceSurfaceWindow(window, mEGLSurface, mEGLContext);
 }
 
-void WindowRenderSurface::MoveResize(Dali::PositionSize positionSize)
+void WindowRenderSurface::UpdatePositionSize(Dali::PositionSize positionSize)
 {
-  bool needToMove   = false;
-  bool needToResize = false;
-
   // Check moving
   if((fabs(positionSize.x - mPositionSize.x) >= MINIMUM_DIMENSION_CHANGE) ||
      (fabs(positionSize.y - mPositionSize.y) >= MINIMUM_DIMENSION_CHANGE))
   {
-    needToMove = true;
-  }
+    mPositionSize.x = positionSize.x;
+    mPositionSize.y = positionSize.y;
 
-  // Check resizing
-  if((fabs(positionSize.width - mPositionSize.width) >= MINIMUM_DIMENSION_CHANGE) ||
-     (fabs(positionSize.height - mPositionSize.height) >= MINIMUM_DIMENSION_CHANGE))
-  {
-    needToResize = true;
+    DALI_LOG_RELEASE_INFO("Update Position by server (%d, %d)\n", mPositionSize.x, mPositionSize.y);
   }
+}
 
-  if(needToResize)
-  {
-    if(needToMove)
-    {
-      mWindowBase->MoveResize(positionSize);
-    }
-    else
-    {
-      mWindowBase->Resize(positionSize);
-    }
-
-    mResizeFinished = false;
-    mPositionSize   = positionSize;
-  }
-  else
-  {
-    if(needToMove)
-    {
-      mWindowBase->Move(positionSize);
+void WindowRenderSurface::MoveResize(Dali::PositionSize positionSize)
+{
+  mPositionSize.x = positionSize.x;
+  mPositionSize.y = positionSize.y;
 
-      mPositionSize = positionSize;
-    }
-  }
+  DALI_LOG_RELEASE_INFO("Update Position by client (%d, %d)\n", positionSize.x, positionSize.y);
 
-  DALI_LOG_INFO(gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::MoveResize: %d, %d, %d, %d\n", mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height);
+  mWindowBase->MoveResize(positionSize);
 }
 
 void WindowRenderSurface::StartRender()
@@ -390,11 +436,12 @@ void WindowRenderSurface::StartRender()
 
 bool WindowRenderSurface::PreRender(bool resizingSurface, const std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect)
 {
-  mDamagedRects.assign(damagedRects.begin(), damagedRects.end());
+  InitializeGraphics();
 
   Dali::Integration::Scene::FrameCallbackContainer callbacks;
 
   Dali::Integration::Scene scene = mScene.GetHandle();
+
   if(scene)
   {
     bool needFrameRenderedTrigger = false;
@@ -464,59 +511,82 @@ bool WindowRenderSurface::PreRender(bool resizingSurface, const std::vector<Rect
     * Notice : PreRotation is not used in the latest tizen,
     *          because output transform event should be occured before egl window is not created.
     */
-
-  if(mIsResizing || mDefaultScreenRotationAvailable)
+  if(scene && resizingSurface)
   {
-    int totalAngle = (mWindowRotationAngle + mScreenRotationAngle) % 360;
+    int  totalAngle                  = 0;
+    bool isScreenOrientationChanging = false;
 
-    // Window rotate or screen rotate
-    if(!mWindowRotationFinished || !mScreenRotationFinished)
+    if(mWindowRotationAngle != scene.GetCurrentSurfaceOrientation())
     {
-      mWindowBase->SetEglWindowBufferTransform(totalAngle);
+      mWindowRotationAngle         = scene.GetCurrentSurfaceOrientation();
+      mIsWindowOrientationChanging = true;
+    }
+
+    if(mScreenRotationAngle != scene.GetCurrentScreenOrientation())
+    {
+      mScreenRotationAngle        = scene.GetCurrentScreenOrientation();
+      isScreenOrientationChanging = true;
+    }
+    totalAngle = (mWindowRotationAngle + mScreenRotationAngle) % 360;
 
-      // Reset only screen rotation flag
-      mScreenRotationFinished = true;
+    DALI_LOG_RELEASE_INFO("Window/Screen orientation ard changed, WinOrientation[%d],flag[%d], ScreenOrientation[%d],flag[%d], total[%d]\n", mWindowRotationAngle, mIsWindowOrientationChanging, mScreenRotationAngle, isScreenOrientationChanging, totalAngle);
 
-      DALI_LOG_RELEASE_INFO("WindowRenderSurface::PreRender: Set rotation [%d] [%d]\n", mWindowRotationAngle, mScreenRotationAngle);
+    Rect<int> surfaceSize = scene.GetCurrentSurfaceRect();
+    //update surface size
+    mPositionSize.width  = surfaceSize.width;
+    mPositionSize.height = surfaceSize.height;
+
+    DALI_LOG_RELEASE_INFO("Window is resizing, (%d, %d), [%d x %d]\n", mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height);
+
+    // Window rotate or screen rotate
+    if(mIsWindowOrientationChanging || isScreenOrientationChanging)
+    {
+      mWindowBase->SetEglWindowBufferTransform(totalAngle);
     }
 
     // Only window rotate
-    if(!mWindowRotationFinished)
+    if(mIsWindowOrientationChanging)
     {
       mWindowBase->SetEglWindowTransform(mWindowRotationAngle);
     }
 
     // Resize case
-    if(!mResizeFinished)
-    {
-      Dali::PositionSize positionSize;
-      positionSize.x = mPositionSize.x;
-      positionSize.y = mPositionSize.y;
-      if(totalAngle == 0 || totalAngle == 180)
-      {
-        positionSize.width  = mPositionSize.width;
-        positionSize.height = mPositionSize.height;
-      }
-      else
-      {
-        positionSize.width  = mPositionSize.height;
-        positionSize.height = mPositionSize.width;
-      }
-      mWindowBase->ResizeEglWindow(positionSize);
-      mResizeFinished = true;
+    Dali::PositionSize positionSize;
 
-      DALI_LOG_RELEASE_INFO("WindowRenderSurface::PreRender: Set resize\n");
+    // Some native resize API(wl_egl_window_resize) has the input parameters of x, y, width and height.
+    // So, position data should be set.
+    positionSize.x = mPositionSize.x;
+    positionSize.y = mPositionSize.y;
+    if(totalAngle == 0 || totalAngle == 180)
+    {
+      positionSize.width  = mPositionSize.width;
+      positionSize.height = mPositionSize.height;
+    }
+    else
+    {
+      positionSize.width  = mPositionSize.height;
+      positionSize.height = mPositionSize.width;
     }
 
+    mWindowBase->ResizeEglWindow(positionSize);
+
     SetFullSwapNextFrame();
-    mDefaultScreenRotationAvailable = false;
   }
 
-  SetBufferDamagedRects(mDamagedRects, clippingRect);
+  SetBufferDamagedRects(damagedRects, clippingRect);
 
-  if(clippingRect.IsEmpty())
+  if(scene)
   {
-    mDamagedRects.clear();
+    Rect<int> surfaceRect = scene.GetCurrentSurfaceRect();
+    if(clippingRect == surfaceRect)
+    {
+      int32_t totalAngle = scene.GetCurrentSurfaceOrientation() + scene.GetCurrentScreenOrientation();
+      if(totalAngle >= 360)
+      {
+        totalAngle -= 360;
+      }
+      mDamagedRects.assign(1, RecalculateRect[std::min(totalAngle / 90, 3)](surfaceRect, surfaceRect));
+    }
   }
 
   // This is now done when the render pass for the render surface begins
@@ -534,25 +604,44 @@ void WindowRenderSurface::PostRender()
     GlImplementation& mGLES = eglGraphics->GetGlesInterface();
     mGLES.PostRender();
 
-    if(mIsResizing)
+    bool needWindowRotationCompleted = false;
+
+    if(mIsWindowOrientationChanging)
     {
-      if(!mWindowRotationFinished)
+      if(mNeedWindowRotationAcknowledgement)
       {
-        if(mThreadSynchronization)
+        Dali::Integration::Scene scene = mScene.GetHandle();
+        if(scene)
         {
-          // Enable PostRender flag
-          mThreadSynchronization->PostRenderStarted();
+          if(scene.IsRotationCompletedAcknowledgementSet())
+          {
+            needWindowRotationCompleted = true;
+          }
         }
+      }
+      else
+      {
+        needWindowRotationCompleted = true;
+      }
+    }
 
-        DALI_LOG_RELEASE_INFO("WindowRenderSurface::PostRender: Trigger rotation event\n");
+    if(needWindowRotationCompleted || mIsImeWindowSurface)
+    {
+      if(mThreadSynchronization)
+      {
+        // Enable PostRender flag
+        mThreadSynchronization->PostRenderStarted();
+      }
 
-        mRotationTrigger->Trigger();
+      if(mIsWindowOrientationChanging || mIsImeWindowSurface)
+      {
+        mPostRenderTrigger->Trigger();
+      }
 
-        if(mThreadSynchronization)
-        {
-          // Wait until the event-thread complete the rotation event processing
-          mThreadSynchronization->PostRenderWaitForCompletion();
-        }
+      if(mThreadSynchronization)
+      {
+        // Wait until the event-thread complete the rotation event processing
+        mThreadSynchronization->PostRenderWaitForCompletion();
       }
     }
 
@@ -604,19 +693,30 @@ Integration::StencilBufferAvailable WindowRenderSurface::GetStencilBufferRequire
   return mGraphics ? mGraphics->GetStencilBufferRequired() : Integration::StencilBufferAvailable::FALSE;
 }
 
+void WindowRenderSurface::InitializeImeSurface()
+{
+  mIsImeWindowSurface = true;
+  if(!mPostRenderTrigger)
+  {
+    mPostRenderTrigger = std::unique_ptr<TriggerEventInterface>(TriggerEventFactory::CreateTriggerEvent(MakeCallback(this, &WindowRenderSurface::ProcessPostRender),
+                                                                                                        TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER));
+  }
+}
+
+void WindowRenderSurface::SetNeedsRotationCompletedAcknowledgement(bool needAcknowledgement)
+{
+  mNeedWindowRotationAcknowledgement = needAcknowledgement;
+}
+
 void WindowRenderSurface::OutputTransformed()
 {
   int screenRotationAngle = mWindowBase->GetScreenRotationAngle();
 
   if(mScreenRotationAngle != screenRotationAngle)
   {
-    mScreenRotationAngle    = screenRotationAngle;
-    mScreenRotationFinished = false;
-    mResizeFinished         = false;
-
     mOutputTransformedSignal.Emit();
 
-    DALI_LOG_RELEASE_INFO("WindowRenderSurface::OutputTransformed: window = %d screen = %d\n", mWindowRotationAngle, mScreenRotationAngle);
+    DALI_LOG_RELEASE_INFO("WindowRenderSurface::OutputTransformed: window = %d new screen angle = %d\n", mWindowRotationAngle, screenRotationAngle);
   }
   else
   {
@@ -624,13 +724,20 @@ void WindowRenderSurface::OutputTransformed()
   }
 }
 
-void WindowRenderSurface::ProcessRotationRequest()
+void WindowRenderSurface::ProcessPostRender()
 {
-  mWindowRotationFinished = true;
-
-  mWindowBase->WindowRotationCompleted(mWindowRotationAngle, mPositionSize.width, mPositionSize.height);
+  if(mIsWindowOrientationChanging)
+  {
+    mWindowRotationFinishedSignal.Emit();
+    mWindowBase->WindowRotationCompleted(mWindowRotationAngle, mPositionSize.width, mPositionSize.height);
+    mIsWindowOrientationChanging = false;
+    DALI_LOG_RELEASE_INFO("WindowRenderSurface::ProcessPostRender: Rotation Done, flag = %d\n", mIsWindowOrientationChanging);
+  }
 
-  DALI_LOG_INFO(gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessRotationRequest: Rotation Done\n");
+  if(mIsImeWindowSurface)
+  {
+    mWindowBase->ImeWindowReadyToRender();
+  }
 
   if(mThreadSynchronization)
   {
@@ -657,13 +764,6 @@ void WindowRenderSurface::ProcessFrameCallback()
 
 void WindowRenderSurface::OnFileDescriptorEventDispatched(FileDescriptorMonitor::EventType eventBitMask, int fileDescriptor)
 {
-  if(!(eventBitMask & FileDescriptorMonitor::FD_READABLE))
-  {
-    DALI_LOG_ERROR("WindowRenderSurface::OnFileDescriptorEventDispatched: file descriptor error [%d]\n", eventBitMask);
-    close(fileDescriptor);
-    return;
-  }
-
   DALI_LOG_RELEASE_INFO("WindowRenderSurface::OnFileDescriptorEventDispatched: Frame rendered [%d]\n", fileDescriptor);
 
   std::unique_ptr<FrameCallbackInfo> callbackInfo;
@@ -681,7 +781,7 @@ void WindowRenderSurface::OnFileDescriptorEventDispatched(FileDescriptorMonitor:
   }
 
   // Call the connected callback
-  if(callbackInfo)
+  if(callbackInfo && (eventBitMask & FileDescriptorMonitor::FD_READABLE))
   {
     for(auto&& iter : (callbackInfo)->callbacks)
     {
@@ -695,53 +795,98 @@ void WindowRenderSurface::SetBufferDamagedRects(const std::vector<Rect<int>>& da
   auto eglGraphics = static_cast<EglGraphics*>(mGraphics);
   if(eglGraphics)
   {
+    // If scene is not exist, just use stored mPositionSize.
+    Rect<int> surfaceRect(0, 0, mPositionSize.width, mPositionSize.height);
+    int32_t   orientation = 0;
+
+    Dali::Integration::Scene scene = mScene.GetHandle();
+    if(scene)
+    {
+      surfaceRect        = scene.GetCurrentSurfaceRect();
+      int32_t totalAngle = scene.GetCurrentSurfaceOrientation() + scene.GetCurrentScreenOrientation();
+      if(totalAngle >= 360)
+      {
+        totalAngle -= 360;
+      }
+      orientation = std::min(totalAngle / 90, 3);
+    }
+
     Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
-    if(!eglImpl.IsPartialUpdateRequired())
+    if(!eglImpl.IsPartialUpdateRequired() || mFullSwapNextFrame)
     {
+      InsertRects(mBufferDamagedRects, surfaceRect);
+      clippingRect = surfaceRect;
       return;
     }
 
-    Rect<int> surfaceRect(0, 0, mPositionSize.width, mPositionSize.height);
-
-    if(mFullSwapNextFrame)
+    if(damagedRects.empty())
     {
-      InsertRects(mBufferDamagedRects, std::vector<Rect<int>>(1, surfaceRect));
+      // Empty damaged rect. We don't need rendering
       clippingRect = Rect<int>();
+      // Clean up current damanged rects.
+      mDamagedRects.clear();
       return;
     }
 
+    mGraphics->ActivateSurfaceContext(this);
+
     EGLint bufferAge = eglImpl.GetBufferAge(mEGLSurface);
 
     // Buffer age 0 means the back buffer in invalid and requires full swap
-    if(!damagedRects.size() || bufferAge == 0)
+    if(bufferAge == 0)
     {
-      InsertRects(mBufferDamagedRects, std::vector<Rect<int>>(1, surfaceRect));
-      clippingRect = Rect<int>();
+      InsertRects(mBufferDamagedRects, surfaceRect);
+      clippingRect = surfaceRect;
       return;
     }
 
+    mDamagedRects.assign(damagedRects.begin(), damagedRects.end());
+
+    // Merge intersecting rects, form an array of non intersecting rects to help driver a bit
+    // Could be optional and can be removed, needs to be checked with and without on platform
+    // And then, Make one clipping rect, and rotate rects by orientation.
+    MergeIntersectingRectsAndRotate(clippingRect, mDamagedRects, orientation, surfaceRect);
+
     // We push current frame damaged rects here, zero index for current frame
-    InsertRects(mBufferDamagedRects, damagedRects);
+    InsertRects(mBufferDamagedRects, clippingRect);
 
     // Merge damaged rects into clipping rect
-    auto bufferDamagedRects = mBufferDamagedRects.begin();
-    while(bufferAge-- >= 0 && bufferDamagedRects != mBufferDamagedRects.end())
+    if(bufferAge <= static_cast<EGLint>(mBufferDamagedRects.size()))
+    {
+      // clippingRect is already the current frame's damaged rect. Merge from the second
+      for(int i = 1; i < bufferAge; i++)
+      {
+        clippingRect.Merge(mBufferDamagedRects[i]);
+      }
+    }
+    else
     {
-      const std::vector<Rect<int>>& rects = *bufferDamagedRects++;
-      MergeRects(clippingRect, rects);
+      // The buffer age is too old. Need full update.
+      clippingRect = surfaceRect;
+      return;
     }
 
     if(!clippingRect.Intersect(surfaceRect) || clippingRect.Area() > surfaceRect.Area() * FULL_UPDATE_RATIO)
     {
       // clipping area too big or doesn't intersect surface rect
-      clippingRect = Rect<int>();
+      clippingRect = surfaceRect;
       return;
     }
 
-    std::vector<Rect<int>> damagedRegion;
-    damagedRegion.push_back(clippingRect);
+    if(!clippingRect.IsEmpty())
+    {
+      std::vector<Rect<int>> damagedRegion;
+      if(scene)
+      {
+        damagedRegion.push_back(RecalculateRect[orientation](clippingRect, surfaceRect));
+      }
+      else
+      {
+        damagedRegion.push_back(clippingRect);
+      }
 
-    eglImpl.SetDamageRegion(mEGLSurface, damagedRegion);
+      eglImpl.SetDamageRegion(mEGLSurface, damagedRegion);
+    }
   }
 }
 
@@ -750,11 +895,9 @@ void WindowRenderSurface::SwapBuffers(const std::vector<Rect<int>>& damagedRects
   auto eglGraphics = static_cast<EglGraphics*>(mGraphics);
   if(eglGraphics)
   {
-    Rect<int> surfaceRect(0, 0, mPositionSize.width, mPositionSize.height);
-
     Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
 
-    if(!eglImpl.IsPartialUpdateRequired() || mFullSwapNextFrame || !damagedRects.size() || (damagedRects[0].Area() > surfaceRect.Area() * FULL_UPDATE_RATIO))
+    if(!eglImpl.IsPartialUpdateRequired() || mFullSwapNextFrame)
     {
       mFullSwapNextFrame = false;
       eglImpl.SwapBuffers(mEGLSurface);
@@ -763,55 +906,22 @@ void WindowRenderSurface::SwapBuffers(const std::vector<Rect<int>>& damagedRects
 
     mFullSwapNextFrame = false;
 
-    std::vector<Rect<int>> mergedRects = damagedRects;
-
-    // Merge intersecting rects, form an array of non intersecting rects to help driver a bit
-    // Could be optional and can be removed, needs to be checked with and without on platform
-    const int n = mergedRects.size();
-    for(int i = 0; i < n - 1; i++)
-    {
-      if(mergedRects[i].IsEmpty())
-      {
-        continue;
-      }
-
-      for(int j = i + 1; j < n; j++)
-      {
-        if(mergedRects[j].IsEmpty())
-        {
-          continue;
-        }
-
-        if(mergedRects[i].Intersects(mergedRects[j]))
-        {
-          mergedRects[i].Merge(mergedRects[j]);
-          mergedRects[j].width  = 0;
-          mergedRects[j].height = 0;
-        }
-      }
-    }
-
-    int j = 0;
-    for(int i = 0; i < n; i++)
-    {
-      if(!mergedRects[i].IsEmpty())
-      {
-        mergedRects[j++] = mergedRects[i];
-      }
-    }
-
-    if(j != 0)
+    Rect<int32_t>            surfaceRect;
+    Dali::Integration::Scene scene = mScene.GetHandle();
+    if(scene)
     {
-      mergedRects.resize(j);
+      surfaceRect = scene.GetCurrentSurfaceRect();
     }
 
-    if(!mergedRects.size() || (mergedRects[0].Area() > surfaceRect.Area() * FULL_UPDATE_RATIO))
+    if(!damagedRects.size() || (damagedRects[0].Area() > surfaceRect.Area() * FULL_UPDATE_RATIO))
     {
+      // In normal cases, WindowRenderSurface::SwapBuffers() will not be called if mergedRects.size() is 0.
+      // For exceptional cases, swap full area.
       eglImpl.SwapBuffers(mEGLSurface);
     }
     else
     {
-      eglImpl.SwapBuffers(mEGLSurface, mergedRects);
+      eglImpl.SwapBuffers(mEGLSurface, damagedRects);
     }
   }
 }