/*
- * 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.
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())
- {
- for(; i < rects.size(); i++)
- {
- if(!rects[i].IsEmpty())
- {
- mergingRect = rects[i];
- break;
- }
- }
- }
-
- for(; i < rects.size(); i++)
- {
- mergingRect.Merge(rects[i]);
- }
-}
-
-void InsertRects(WindowRenderSurface::DamagedRectsContainer& damagedRectsList, const std::vector<Rect<int>>& damagedRects)
-{
- damagedRectsList.push_front(damagedRects);
+ damagedRectsList.insert(damagedRectsList.begin(), damagedRects);
if(damagedRectsList.size() > 4) // past triple buffers + current
{
damagedRectsList.pop_back();
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++)
+ {
+ if(damagedRects[i].IsEmpty())
+ {
+ continue;
+ }
+
+ for(int j = i + 1; j < n; j++)
+ {
+ if(damagedRects[j].IsEmpty())
+ {
+ continue;
+ }
+
+ if(damagedRects[i].Intersects(damagedRects[j]))
+ {
+ damagedRects[i].Merge(damagedRects[j]);
+ damagedRects[j].width = 0;
+ damagedRects[j].height = 0;
+ }
+ }
+ }
+
+ int j = 0;
+ for(int i = 0; i < n; 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);
+ }
+ }
+
+ if(j != 0)
+ {
+ damagedRects.resize(j);
+ }
+}
+
} // unnamed namespace
WindowRenderSurface::WindowRenderSurface(Dali::PositionSize positionSize, Any surface, bool isTransparent)
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(),
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);
WindowRenderSurface::~WindowRenderSurface()
{
- if(mRotationTrigger)
- {
- delete mRotationTrigger;
- }
}
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);
}
}
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()
return mOutputTransformedSignal;
}
+WindowRenderSurface::RotationFinishedSignalType& WindowRenderSurface::RotationFinishedSignal()
+{
+ return mWindowRotationFinishedSignal;
+}
+
PositionSize WindowRenderSurface::GetPositionSize() const
{
return mPositionSize;
dpiVertical = mDpiVertical;
}
-int WindowRenderSurface::GetOrientation() const
+int WindowRenderSurface::GetSurfaceOrientation() const
+{
+ return mWindowBase->GetWindowRotationAngle();
+}
+
+int WindowRenderSurface::GetScreenOrientation() const
{
- return mWindowBase->GetOrientation();
+ 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);
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,
// 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()
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;
* 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;
+ }
- // Reset only screen rotation flag
- mScreenRotationFinished = true;
+ if(mScreenRotationAngle != scene.GetCurrentScreenOrientation())
+ {
+ mScreenRotationAngle = scene.GetCurrentScreenOrientation();
+ isScreenOrientationChanging = true;
+ }
+ totalAngle = (mWindowRotationAngle + mScreenRotationAngle) % 360;
- DALI_LOG_RELEASE_INFO("WindowRenderSurface::PreRender: Set rotation [%d] [%d]\n", mWindowRotationAngle, mScreenRotationAngle);
+ 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);
+
+ 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
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();
}
}
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
{
}
}
-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)
{
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;
}
// Call the connected callback
- if(callbackInfo)
+ if(callbackInfo && (eventBitMask & FileDescriptorMonitor::FD_READABLE))
{
for(auto&& iter : (callbackInfo)->callbacks)
{
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()))
{
- const std::vector<Rect<int>>& rects = *bufferDamagedRects++;
- MergeRects(clippingRect, rects);
+ // 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
+ {
+ // 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;
- Dali::Integration::Scene scene = mScene.GetHandle();
- if(scene)
- {
- damagedRegion.push_back(RecalculateRect[std::min(scene.GetCurrentSurfaceOrientation() / 90, 3)](clippingRect, scene.GetCurrentSurfaceRect()));
- }
- else
+ if(!clippingRect.IsEmpty())
{
- damagedRegion.push_back(clippingRect);
- }
+ 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);
+ }
}
}
auto eglGraphics = static_cast<EglGraphics*>(mGraphics);
if(eglGraphics)
{
- Rect<int32_t> surfaceRect;
- int32_t orientation = 0;
-
- Dali::Integration::Scene scene = mScene.GetHandle();
- if(scene)
- {
- surfaceRect = scene.GetCurrentSurfaceRect();
- orientation = std::min(scene.GetCurrentSurfaceOrientation() / 90, 3);
- }
-
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);
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++] = RecalculateRect[orientation](mergedRects[i], surfaceRect);
- }
- }
-
- 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);
}
}
}