/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
}
}
-void InsertRects(WindowRenderSurface::DamagedRectsContainer& damagedRectsList, const std::vector<Rect<int>>& damagedRects)
+void InsertRects(WindowRenderSurface::DamagedRectsContainer& damagedRectsList, const 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 MergeIntersectingRects(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())
+ {
+ 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->SetTransparency(transparent);
}
-void WindowRenderSurface::RequestRotation(int angle, int width, int height)
+void WindowRenderSurface::RequestRotation(int angle, PositionSize positionSize)
{
if(!mPostRenderTrigger)
{
mPostRenderTrigger = std::unique_ptr<TriggerEventInterface>(TriggerEventFactory::CreateTriggerEvent(MakeCallback(this, &WindowRenderSurface::ProcessPostRender),
- TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER));
+ TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER));
}
- mPositionSize.width = width;
- mPositionSize.height = height;
+ mPositionSize = positionSize;
mWindowRotationAngle = angle;
mWindowRotationFinished = false;
mWindowBase->SetWindowRotationAngle(mWindowRotationAngle);
- DALI_LOG_INFO(gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: angle = %d screen rotation = %d\n", mWindowRotationAngle, mScreenRotationAngle);
+ DALI_LOG_RELEASE_INFO("angle = %d screen rotation = %d, flag = %d\n", mWindowRotationAngle, mScreenRotationAngle, mWindowRotationFinished);
}
WindowBase* WindowRenderSurface::GetWindowBase()
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,
return eglImpl.ReplaceSurfaceWindow(window, mEGLSurface, mEGLContext);
}
+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;
+ }
+
+ // Check resizing
+ if((fabs(positionSize.width - mPositionSize.width) >= MINIMUM_DIMENSION_CHANGE) ||
+ (fabs(positionSize.height - mPositionSize.height) >= MINIMUM_DIMENSION_CHANGE))
+ {
+ needToResize = true;
+ }
+
+ if(needToResize)
+ {
+ mResizeFinished = false;
+ mPositionSize = positionSize;
+ }
+ else
+ {
+ if(needToMove)
+ {
+ mPositionSize = positionSize;
+ }
+ }
+
+ DALI_LOG_INFO(gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::MoveResize: %d, %d, %d, %d\n", mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height);
+}
+
void WindowRenderSurface::MoveResize(Dali::PositionSize positionSize)
{
bool needToMove = false;
{
InitializeGraphics();
- mDamagedRects.assign(damagedRects.begin(), damagedRects.end());
-
Dali::Integration::Scene::FrameCallbackContainer callbacks;
Dali::Integration::Scene scene = mScene.GetHandle();
mWindowBase->ResizeEglWindow(positionSize);
mResizeFinished = true;
- DALI_LOG_RELEASE_INFO("WindowRenderSurface::PreRender: Set resize, x: %d, y: %d, w: %d, h:%d\n", positionSize.x, positionSize.y, positionSize.width, positionSize.height);
+ DALI_LOG_RELEASE_INFO("WindowRenderSurface::PreRender: Set resize, totalAngle: %d, x: %d, y: %d, w: %d, h:%d\n", totalAngle, positionSize.x, positionSize.y, positionSize.width, positionSize.height);
}
SetFullSwapNextFrame();
mDefaultScreenRotationAvailable = false;
}
- SetBufferDamagedRects(mDamagedRects, clippingRect);
+ SetBufferDamagedRects(damagedRects, clippingRect);
- Rect<int> surfaceRect(0, 0, mPositionSize.width, mPositionSize.height);
- if(clippingRect == surfaceRect)
- {
- mDamagedRects.assign(1, surfaceRect);
- }
- else if(mDamagedRects.empty() && !clippingRect.IsEmpty())
+ if(scene)
{
- // We will render clippingRect area but mDamagedRects is empty.
- // So make mDamagedRects same with clippingRect to swap buffers.
- mDamagedRects.assign(1, clippingRect);
+ Rect<int> surfaceRect = scene.GetCurrentSurfaceRect();
+ if(clippingRect == surfaceRect)
+ {
+ mDamagedRects.assign(1, surfaceRect);
+ }
}
// This is now done when the render pass for the render surface begins
}
}
+bool WindowRenderSurface::IsWindowRotating() const
+{
+ return !(mWindowRotationFinished);
+}
+
void WindowRenderSurface::ProcessPostRender()
{
if(!mWindowRotationFinished)
{
mWindowBase->WindowRotationCompleted(mWindowRotationAngle, mPositionSize.width, mPositionSize.height);
- DALI_LOG_RELEASE_INFO("WindowRenderSurface::ProcessPostRender: Rotation Done\n");
mWindowRotationFinished = true;
+ DALI_LOG_RELEASE_INFO("WindowRenderSurface::ProcessPostRender: Rotation Done, flag = %d\n", mWindowRotationFinished);
}
if(mIsImeWindowSurface)
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();
+ orientation = std::min(scene.GetCurrentSurfaceOrientation() / 90, 3);
+ }
Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
if(!eglImpl.IsPartialUpdateRequired() || mFullSwapNextFrame)
{
- InsertRects(mBufferDamagedRects, std::vector<Rect<int>>(1, surfaceRect));
+ InsertRects(mBufferDamagedRects, surfaceRect);
clippingRect = surfaceRect;
return;
}
+ if(damagedRects.empty())
+ {
+ // Empty damaged rect. We don't need rendering
+ clippingRect = Rect<int>();
+ return;
+ }
+
mGraphics->ActivateSurfaceContext(this);
EGLint bufferAge = eglImpl.GetBufferAge(mEGLSurface);
// Buffer age 0 means the back buffer in invalid and requires full swap
if(bufferAge == 0)
{
- InsertRects(mBufferDamagedRects, std::vector<Rect<int>>(1, surfaceRect));
+ 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
+ MergeIntersectingRects(mDamagedRects, orientation, surfaceRect);
+
+ // Make one clipping rect
+ MergeRects(clippingRect, mDamagedRects);
+
// 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)
if(!clippingRect.IsEmpty())
{
- std::vector<Rect<int>> damagedRegion;
- Dali::Integration::Scene scene = mScene.GetHandle();
+ std::vector<Rect<int>> damagedRegion;
if(scene)
{
damagedRegion.push_back(RecalculateRect[std::min(scene.GetCurrentSurfaceOrientation() / 90, 3)](clippingRect, scene.GetCurrentSurfaceRect()));
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() != 0 && 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.
}
else
{
- eglImpl.SwapBuffers(mEGLSurface, mergedRects);
+ eglImpl.SwapBuffers(mEGLSurface, damagedRects);
}
}
}