}
}
+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};
+
} // unnamed namespace
WindowRenderSurface::WindowRenderSurface(Dali::PositionSize positionSize, Any surface, bool isTransparent)
mWindowBase(),
mThreadSynchronization(nullptr),
mRenderNotification(nullptr),
- mRotationTrigger(nullptr),
+ mPostRenderTrigger(),
mFrameRenderedTrigger(),
mGraphics(nullptr),
mEGLSurface(nullptr),
mWindowRotationFinished(true),
mScreenRotationFinished(true),
mResizeFinished(true),
- mDefaultScreenRotationAvailable(false)
+ mDefaultScreenRotationAvailable(false),
+ mIsImeWindowSurface(false),
+ mNeedWindowRotationAcknowledgement(false)
{
DALI_LOG_INFO(gWindowRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n");
Initialize(surface);
WindowRenderSurface::~WindowRenderSurface()
{
- if(mRotationTrigger)
- {
- delete mRotationTrigger;
- }
}
void WindowRenderSurface::Initialize(Any surface)
void WindowRenderSurface::RequestRotation(int angle, int width, int height)
{
- 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;
mWindowRotationAngle = angle;
mWindowRotationFinished = false;
+ mResizeFinished = 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()
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);
bool needToResize = false;
// Check moving
- if((fabs(positionSize.x - mPositionSize.x) > MINIMUM_DIMENSION_CHANGE) ||
- (fabs(positionSize.y - mPositionSize.y) > MINIMUM_DIMENSION_CHANGE))
+ 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))
+ if((fabs(positionSize.width - mPositionSize.width) >= MINIMUM_DIMENSION_CHANGE) ||
+ (fabs(positionSize.height - mPositionSize.height) >= MINIMUM_DIMENSION_CHANGE))
{
needToResize = true;
}
bool WindowRenderSurface::PreRender(bool resizingSurface, const std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect)
{
+ InitializeGraphics();
+
mDamagedRects.assign(damagedRects.begin(), damagedRects.end());
Dali::Integration::Scene::FrameCallbackContainer callbacks;
mWindowBase->ResizeEglWindow(positionSize);
mResizeFinished = true;
- DALI_LOG_RELEASE_INFO("WindowRenderSurface::PreRender: Set resize\n");
+ 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);
}
SetFullSwapNextFrame();
SetBufferDamagedRects(mDamagedRects, clippingRect);
- if(clippingRect.IsEmpty())
+ if(scene)
{
- mDamagedRects.clear();
+ Rect<int> surfaceRect = scene.GetCurrentSurfaceRect();
+ if(clippingRect == surfaceRect)
+ {
+ mDamagedRects.assign(1, surfaceRect);
+ }
+ else if(mDamagedRects.empty() && !clippingRect.IsEmpty())
+ {
+ // We will render clippingRect area but mDamagedRects is empty.
+ // So make mDamagedRects same with clippingRect to swap buffers.
+ mDamagedRects.assign(1, clippingRect);
+ }
}
// 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(!mWindowRotationFinished)
{
- 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
+ {
+ if(mIsResizing)
+ {
+ 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(!mWindowRotationFinished || 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();
}
}
-void WindowRenderSurface::ProcessRotationRequest()
+bool WindowRenderSurface::IsWindowRotating() const
{
- mWindowRotationFinished = true;
+ return !(mWindowRotationFinished);
+}
- mWindowBase->WindowRotationCompleted(mWindowRotationAngle, mPositionSize.width, mPositionSize.height);
+void WindowRenderSurface::ProcessPostRender()
+{
+ if(!mWindowRotationFinished)
+ {
+ mWindowBase->WindowRotationCompleted(mWindowRotationAngle, mPositionSize.width, mPositionSize.height);
+ mWindowRotationFinished = true;
+ DALI_LOG_RELEASE_INFO("WindowRenderSurface::ProcessPostRender: Rotation Done, flag = %d\n", mWindowRotationFinished);
+ }
- DALI_LOG_INFO(gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessRotationRequest: Rotation Done\n");
+ if(mIsImeWindowSurface)
+ {
+ mWindowBase->ImeWindowReadyToRender();
+ }
if(mThreadSynchronization)
{
auto eglGraphics = static_cast<EglGraphics*>(mGraphics);
if(eglGraphics)
{
- Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
- if(!eglImpl.IsPartialUpdateRequired())
+ // If scene is not exist, just use stored mPositionSize.
+ Rect<int> surfaceRect(0, 0, mPositionSize.width, mPositionSize.height);
+
+ Dali::Integration::Scene scene = mScene.GetHandle();
+ if(scene)
{
- return;
+ surfaceRect = scene.GetCurrentSurfaceRect();
}
- Rect<int> surfaceRect(0, 0, mPositionSize.width, mPositionSize.height);
-
- if(mFullSwapNextFrame)
+ Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
+ if(!eglImpl.IsPartialUpdateRequired() || mFullSwapNextFrame)
{
InsertRects(mBufferDamagedRects, std::vector<Rect<int>>(1, surfaceRect));
- clippingRect = Rect<int>();
+ clippingRect = surfaceRect;
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>();
+ 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[std::min(scene.GetCurrentSurfaceOrientation() / 90, 3)](clippingRect, scene.GetCurrentSurfaceRect()));
+ }
+ else
+ {
+ damagedRegion.push_back(clippingRect);
+ }
- eglImpl.SetDamageRegion(mEGLSurface, damagedRegion);
+ eglImpl.SetDamageRegion(mEGLSurface, damagedRegion);
+ }
}
}
auto eglGraphics = static_cast<EglGraphics*>(mGraphics);
if(eglGraphics)
{
- Rect<int> surfaceRect(0, 0, mPositionSize.width, mPositionSize.height);
+ 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 || (damagedRects.size() != 0 && damagedRects[0].Area() > surfaceRect.Area() * FULL_UPDATE_RATIO))
{
mFullSwapNextFrame = false;
eglImpl.SwapBuffers(mEGLSurface);
{
if(!mergedRects[i].IsEmpty())
{
- mergedRects[j++] = mergedRects[i];
+ mergedRects[j++] = RecalculateRect[orientation](mergedRects[i], surfaceRect);
}
}
if(!mergedRects.size() || (mergedRects[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