From: Eunki, Hong Date: Tue, 19 Nov 2024 10:36:07 +0000 (+0900) Subject: (CanvasView) Retry rasterization again if last rasterization failed X-Git-Tag: dali_2.3.52~8 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F18%2F320618%2F10;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git (CanvasView) Retry rasterization again if last rasterization failed Let we retry canvas rasterizing if last commit was failed. Change-Id: Id8cc862f0c640ed34567e54a6f8218ad5578ddae Signed-off-by: Eunki, Hong --- diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor-impl.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor-impl.h index f4a61f82b3..e56a83c48b 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor-impl.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor-impl.h @@ -72,6 +72,7 @@ public: void RunIdles(); void RequestUpdateOnce(); + void RequestProcessEventsOnIdle(); static Integration::Scene GetScene(Dali::Window window); diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor.cpp index 488d2d6d43..7291db8b86 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor.cpp @@ -114,11 +114,9 @@ bool Adaptor::AddIdle(CallbackBase* callback, bool hasReturnValue) void Adaptor::RemoveIdle(CallbackBase* callback) { - mCallbacks.Erase(std::remove_if(mCallbacks.Begin(), mCallbacks.End(), [&callback](CallbackBase* current) - { return callback == current; }), + mCallbacks.Erase(std::remove_if(mCallbacks.Begin(), mCallbacks.End(), [&callback](CallbackBase* current) { return callback == current; }), mCallbacks.End()); - mReturnCallbacks.Erase(std::remove_if(mReturnCallbacks.Begin(), mReturnCallbacks.End(), [&callback](CallbackBase* current) - { return callback == current; }), + mReturnCallbacks.Erase(std::remove_if(mReturnCallbacks.Begin(), mReturnCallbacks.End(), [&callback](CallbackBase* current) { return callback == current; }), mReturnCallbacks.End()); } @@ -156,6 +154,19 @@ void Adaptor::RequestUpdateOnce() } } +void Adaptor::RequestProcessEventsOnIdle() +{ + if(mTestApplication) + { + tet_printf("Adaptor::RequestProcessEventsOnIdle()\n"); + + // Note that, toolkit-adaptor is not subclass of RenderController. + // So we should call this function directly. + auto& renderController = mTestApplication->GetRenderController(); + renderController.RequestProcessEventsOnIdle(); + } +} + Dali::Integration::RenderSurfaceInterface& Adaptor::GetSurface() { DALI_ASSERT_ALWAYS(!mWindows.empty()); @@ -413,6 +424,11 @@ void Adaptor::SceneCreated() { } +void Adaptor::RequestProcessEventsOnIdle() +{ + mImpl->RequestProcessEventsOnIdle(); +} + class LogFactory : public LogFactoryInterface { public: diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-async-task-manager.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-async-task-manager.cpp index c6922a59f2..2f0ecbcd59 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-async-task-manager.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-async-task-manager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 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. @@ -154,6 +154,7 @@ private: Dali::Mutex mWaitingTasksMutex; ///< Mutex for mWaitingTasks. We can lock mRunningTasksMutex and mCompletedTasksMutex under this scope. Dali::Mutex mRunningTasksMutex; ///< Mutex for mRunningTasks. We can lock mCompletedTasksMutex under this scope. Dali::Mutex mCompletedTasksMutex; ///< Mutex for mCompletedTasks. We cannot lock any mutex under this scope. + Dali::Mutex mTasksMutex; ///< Mutex for mTasks. We cannot lock any mutex under this scope. std::unique_ptr mTrigger; @@ -678,18 +679,23 @@ void AsyncTaskManager::AddTask(AsyncTaskPtr task) } } - size_t count = mTasks.GetElementCount(); - size_t index = 0; - while(index++ < count) { - auto processHelperIt = mTasks.GetNext(); - DALI_ASSERT_ALWAYS(processHelperIt != mTasks.End()); - if(processHelperIt->Request()) + Mutex::ScopedLock lock(mTasksMutex); + size_t count = mTasks.GetElementCount(); + size_t index = 0; + while(index++ < count) { - break; + auto processHelperIt = mTasks.GetNext(); + DALI_ASSERT_ALWAYS(processHelperIt != mTasks.End()); + if(processHelperIt->Request()) + { + break; + } + // If all threads are busy, then it's ok just to push the task because they will try to get the next job. } - // If all threads are busy, then it's ok just to push the task because they will try to get the next job. } + + // Note : We will not use Processor for toolkit utc } void AsyncTaskManager::RemoveTask(AsyncTaskPtr task) @@ -924,16 +930,32 @@ AsyncTaskPtr AsyncTaskManager::PopNextTaskToProcess() { if((*iter)->IsReady()) { - nextTask = *iter; + bool taskAvaliable = true; - // Add Running queue + // Check whether we try to running same task at multiple threads. { - // Lock while popping task out from the queue Mutex::ScopedLock lock(mRunningTasksMutex); // We can lock this mutex under mWaitingTasksMutex. + auto task = *iter; + auto jter = std::find_if(mRunningTasks.begin(), mRunningTasks.end(), [task](const AsyncRunningTaskPair& element) { return element.first == task; }); + if(jter != mRunningTasks.end()) + { + taskAvaliable = false; + } + } + + if(taskAvaliable) + { + nextTask = *iter; + + // Add Running queue + { + // Lock while popping task out from the queue + Mutex::ScopedLock lock(mRunningTasksMutex); // We can lock this mutex under mWaitingTasksMutex. - mRunningTasks.insert(mRunningTasks.end(), std::make_pair(nextTask, RunningTaskState::RUNNING)); + mRunningTasks.insert(mRunningTasks.end(), std::make_pair(nextTask, RunningTaskState::RUNNING)); - mWaitingTasks.erase(iter); + mWaitingTasks.erase(iter); + } } break; } @@ -945,52 +967,64 @@ AsyncTaskPtr AsyncTaskManager::PopNextTaskToProcess() /// Worker thread called void AsyncTaskManager::CompleteTask(AsyncTaskPtr&& task) { - bool notify = false; - if(task) { bool needTrigger = false; - // Lock while check validation of task. + // Check now whether we need to execute callback or not, for worker thread cases. + if(task->GetCallbackInvocationThread() == AsyncTask::ThreadType::WORKER_THREAD) { - Mutex::ScopedLock lock(mRunningTasksMutex); + bool notify = false; - auto iter = std::find_if(mRunningTasks.begin(), mRunningTasks.end(), [task](const AsyncRunningTaskPair& element) { return element.first == task; }); - if(iter != mRunningTasks.end()) + // Lock while check validation of task. { - if(iter->second == RunningTaskState::RUNNING) + Mutex::ScopedLock lock(mRunningTasksMutex); + + auto iter = std::find_if(mRunningTasks.begin(), mRunningTasks.end(), [task](const AsyncRunningTaskPair& element) { return element.first == task; }); + if(iter != mRunningTasks.end()) { - // This task is valid. - notify = true; + if(iter->second == RunningTaskState::RUNNING) + { + // This task is valid. + notify = true; + } } } - } - - // We should execute this tasks complete callback out of mutex - if(notify && task->GetCallbackInvocationThread() == AsyncTask::ThreadType::WORKER_THREAD) - { - CallbackBase::Execute(*(task->GetCompletedCallback()), task); - // We need to remove task trace now. - if(mTasksCompletedImpl->IsTasksCompletedCallbackExist()) + // We should execute this tasks complete callback out of mutex + if(notify) { - mTasksCompletedImpl->RemoveTaskTrace(task); + CallbackBase::Execute(*(task->GetCompletedCallback()), task); - if(mTasksCompletedImpl->IsExecuteCallbackExist()) + // We need to remove task trace now. + if(mTasksCompletedImpl->IsTasksCompletedCallbackExist()) { - // We need to call EmitCompletedTasks(). Trigger main thread. - needTrigger = true; + mTasksCompletedImpl->RemoveTaskTrace(task); + + if(mTasksCompletedImpl->IsExecuteCallbackExist()) + { + // We need to call EmitCompletedTasks(). Trigger main thread. + needTrigger = true; + } } } } // Lock while adding task to the queue { + bool notify = false; + Mutex::ScopedLock lock(mRunningTasksMutex); auto iter = std::find_if(mRunningTasks.begin(), mRunningTasks.end(), [task](const AsyncRunningTaskPair& element) { return element.first == task; }); if(iter != mRunningTasks.end()) { + if(iter->second == RunningTaskState::RUNNING) + { + // This task is valid. + notify = true; + } + // Move task into completed, for ensure that AsyncTask destroy at main thread. { Mutex::ScopedLock lock(mCompletedTasksMutex); // We can lock this mutex under mRunningTasksMutex. @@ -1098,13 +1132,13 @@ void DestroyAsyncTaskManager() Dali::Internal::Adaptor::gAsyncTaskManager.Reset(); } -void ProcessSingleCompletedTask() +void ProcessSingleCompletedTasks() { auto asyncTaskManager = Dali::AsyncTaskManager::Get(); Dali::Internal::Adaptor::GetImplementation(asyncTaskManager).TaskCompleted(); } -void ProcessAllCompletedTask() +void ProcessAllCompletedTasks() { auto asyncTaskManager = Dali::AsyncTaskManager::Get(); Dali::Internal::Adaptor::GetImplementation(asyncTaskManager).TaskAllCompleted(); diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-canvas-renderer.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-canvas-renderer.cpp index 726648a049..a0b3564bd1 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-canvas-renderer.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-canvas-renderer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 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. @@ -15,31 +15,33 @@ * */ -#include #include +#include #include #include +#include #include #include -#include #include -#include +#include +namespace +{ +bool gRasterizeCalled = false; +bool gRasterizeResult = true; ///< Default rasterization result as success +} // namespace namespace Dali { - namespace Internal { - namespace Adaptor { - -class CanvasRenderer: public Dali::BaseObject +class CanvasRenderer : public Dali::BaseObject { public: - CanvasRenderer( const Vector2& size ) + CanvasRenderer(const Vector2& size) : mDrawable(nullptr), - mTexture ( Dali::Texture::New( Dali::TextureType::TEXTURE_2D, Pixel::RGBA8888, size.width, size.height ) ), + mTexture(Dali::Texture::New(Dali::TextureType::TEXTURE_2D, Pixel::RGBA8888, size.width, size.height)), mSize(size), mViewBox(size) { @@ -51,12 +53,12 @@ public: bool Commit() { - return true; + return true; } bool IsCanvasChanged() const { - return true; + return true; } Dali::Texture GetRasterizedTexture() @@ -66,12 +68,13 @@ public: bool Rasterize() { - return true; + gRasterizeCalled = true; + return gRasterizeResult; } bool AddDrawable(Dali::CanvasRenderer::Drawable& drawable) { - if (!drawable) + if(!drawable) { return false; } @@ -81,11 +84,11 @@ public: bool RemoveDrawable(Dali::CanvasRenderer::Drawable& drawable) { - if (!drawable) + if(!drawable) { return false; } - if (mDrawable == &drawable) + if(mDrawable == &drawable) { mDrawable = nullptr; return true; @@ -95,7 +98,7 @@ public: bool RemoveAllDrawables() { - if (mDrawable) + if(mDrawable) { return true; } @@ -106,7 +109,7 @@ public: { mSize = size; // For negative test - if ( size.width == -999 && size.height == -999 ) + if(size.width == -999 && size.height == -999) { return false; } @@ -122,7 +125,7 @@ public: { mViewBox = viewBox; // For negative test - if ( viewBox.width == -999 && viewBox.height == -999 ) + if(viewBox.width == -999 && viewBox.height == -999) { return false; } @@ -135,40 +138,39 @@ public: } public: - Dali::CanvasRenderer::Drawable* mDrawable; - Dali::Texture mTexture; - Vector2 mSize; - Vector2 mViewBox; + Dali::CanvasRenderer::Drawable* mDrawable; + Dali::Texture mTexture; + Vector2 mSize; + Vector2 mViewBox; }; -inline CanvasRenderer& GetImplementation( Dali::CanvasRenderer& renderer ) +inline CanvasRenderer& GetImplementation(Dali::CanvasRenderer& renderer) { - DALI_ASSERT_ALWAYS( renderer && "CanvasRenderer handle is empty." ); + DALI_ASSERT_ALWAYS(renderer && "CanvasRenderer handle is empty."); BaseObject& handle = renderer.GetBaseObject(); - return static_cast< Internal::Adaptor::CanvasRenderer& >( handle ); + return static_cast(handle); } -inline const CanvasRenderer& GetImplementation( const Dali::CanvasRenderer& renderer ) +inline const CanvasRenderer& GetImplementation(const Dali::CanvasRenderer& renderer) { - DALI_ASSERT_ALWAYS( renderer && "CanvasRenderer handle is empty." ); + DALI_ASSERT_ALWAYS(renderer && "CanvasRenderer handle is empty."); const BaseObject& handle = renderer.GetBaseObject(); - return static_cast< const Internal::Adaptor::CanvasRenderer& >( handle ); + return static_cast(handle); } } // namespace Adaptor } // namespace Internal - /********************************************************************************/ /********************************* PUBLIC CLASS *******************************/ /********************************************************************************/ -CanvasRenderer CanvasRenderer::New( const Vector2& size ) +CanvasRenderer CanvasRenderer::New(const Vector2& size) { Internal::Adaptor::CanvasRenderer* imageRenderer = new Internal::Adaptor::CanvasRenderer(size); - return CanvasRenderer( imageRenderer ); + return CanvasRenderer(imageRenderer); } CanvasRenderer::CanvasRenderer() @@ -179,8 +181,8 @@ CanvasRenderer::~CanvasRenderer() { } -CanvasRenderer::CanvasRenderer( Internal::Adaptor::CanvasRenderer* internal ) -: BaseHandle( internal ) +CanvasRenderer::CanvasRenderer(Internal::Adaptor::CanvasRenderer* internal) +: BaseHandle(internal) { } @@ -240,3 +242,21 @@ const Vector2& CanvasRenderer::GetViewBox() } } // namespace Dali + +namespace Test::CanvasRenderer +{ +void MarkRasterizationResult(bool result) +{ + gRasterizeResult = result; +} + +void ResetRasterizationFlag() +{ + gRasterizeCalled = false; +} + +bool IsRasterizationCalled() +{ + return gRasterizeCalled; +} +} // namespace Test::CanvasRenderer \ No newline at end of file diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-canvas-renderer.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-canvas-renderer.h new file mode 100644 index 0000000000..1087fb697a --- /dev/null +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-canvas-renderer.h @@ -0,0 +1,37 @@ +#ifndef DALI_TOOLKIT_TOOLKIT_CANVAS_RENDERER_H +#define DALI_TOOLKIT_TOOLKIT_CANVAS_RENDERER_H + +/* + * Copyright (c) 2024 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + +namespace Test::CanvasRenderer +{ +// Set global rasterization result for CanvaseRender Rasterize() function. +void MarkRasterizationResult(bool result); + +// Reset CanvaseRender Rasterize() function called signal. +void ResetRasterizationFlag(); + +// Get CanvaseRender Rasterize() function called or not. +bool IsRasterizationCalled(); + +} // namespace Test::CanvasRenderer + +#endif // DALI_TOOLKIT_TOOLKIT_CANVAS_RENDERER_H diff --git a/automated-tests/src/dali-toolkit/utc-Dali-CanvasView.cpp b/automated-tests/src/dali-toolkit/utc-Dali-CanvasView.cpp index febdf970e2..e0bbdb4cb6 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-CanvasView.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-CanvasView.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -43,10 +44,18 @@ namespace void utc_dali_toolkit_canvasview_startup(void) { test_return_value = TET_UNDEF; + + // Make sure we clean up test result before start. + Test::CanvasRenderer::MarkRasterizationResult(true); + Test::CanvasRenderer::ResetRasterizationFlag(); } void utc_dali_toolkit_canvasview_cleanup(void) { + // Make sure we clean up test result after finish. + Test::CanvasRenderer::MarkRasterizationResult(true); + Test::CanvasRenderer::ResetRasterizationFlag(); + test_return_value = TET_PASS; } @@ -271,11 +280,14 @@ int UtcDaliCanvasViewSizeN(void) END_TEST; } +namespace +{ bool gRasterizationCompletedSignal = false; void rasteriztionCompleted(IntrusivePtr task) { gRasterizationCompletedSignal = true; } +} // namespace int UtcDaliCanvasViewRasterizeTaskP(void) { @@ -341,16 +353,6 @@ int UtcDaliCanvasViewRasterizeTaskAddRemoveTaskP(void) END_TEST; } -PixelData CreatePixelData(unsigned int width, unsigned int height) -{ - unsigned int bufferSize = width * height * Pixel::GetBytesPerPixel(Pixel::RGBA8888); - - unsigned char* buffer = reinterpret_cast(malloc(bufferSize)); - PixelData pixelData = PixelData::New(buffer, bufferSize, width, height, Pixel::RGBA8888, PixelData::FREE); - - return pixelData; -} - int UtcDaliCanvasViewRasterizeThreadRasterizationCompletedSignalP(void) { ToolkitTestApplication application; @@ -511,10 +513,12 @@ int UtcDaliCanvasViewRasterizationRequestManually(void) CanvasView canvasView = CanvasView::New(Vector2(300, 300)); DALI_TEST_CHECK(canvasView); + Test::CanvasRenderer::ResetRasterizationFlag(); + application.GetScene().Add(canvasView); canvasView.SetProperty(Actor::Property::SIZE, Vector2(300, 300)); - canvasView.SetProperty(Toolkit::CanvasView::Property::SYNCHRONOUS_LOADING, false); + canvasView.SetProperty(Toolkit::CanvasView::Property::SYNCHRONOUS_LOADING, true); Dali::CanvasRenderer::Shape shape = Dali::CanvasRenderer::Shape::New(); @@ -526,7 +530,8 @@ int UtcDaliCanvasViewRasterizationRequestManually(void) application.Render(); // Rasterization occured - DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), true, TEST_LOCATION); + Test::CanvasRenderer::ResetRasterizationFlag(); bool isRasterizationManually = canvasView.GetProperty(Toolkit::CanvasView::Property::RASTERIZATION_REQUEST_MANUALLY).Get(); DALI_TEST_EQUALS(isRasterizationManually, false, TEST_LOCATION); @@ -540,8 +545,8 @@ int UtcDaliCanvasViewRasterizationRequestManually(void) application.Render(); // Check if the canvasView is rasterized. - // Rasterization occured - DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), true, TEST_LOCATION); + Test::CanvasRenderer::ResetRasterizationFlag(); canvasView.SetProperty(Toolkit::CanvasView::Property::RASTERIZATION_REQUEST_MANUALLY, true); @@ -550,7 +555,11 @@ int UtcDaliCanvasViewRasterizationRequestManually(void) // Rasterization occured // (Note that we cannot 'cancel' the latest rasterization request even if we set RASTERIZATION_REQUEST_MANUALLY to true) - DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), true, TEST_LOCATION); + Test::CanvasRenderer::ResetRasterizationFlag(); + + application.SendNotification(); + application.Render(); isRasterizationManually = canvasView.GetProperty(Toolkit::CanvasView::Property::RASTERIZATION_REQUEST_MANUALLY).Get(); DALI_TEST_EQUALS(isRasterizationManually, true, TEST_LOCATION); @@ -560,7 +569,8 @@ int UtcDaliCanvasViewRasterizationRequestManually(void) application.Render(); // Check if the canvasView is not rasterized. - DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1, 0), false, TEST_LOCATION); + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), false, TEST_LOCATION); + Test::CanvasRenderer::ResetRasterizationFlag(); Dali::CanvasRenderer::Shape shape2 = Dali::CanvasRenderer::Shape::New(); @@ -572,16 +582,209 @@ int UtcDaliCanvasViewRasterizationRequestManually(void) application.Render(); // Check whether the canvasView is not rasterized even if we add drawables. + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), false, TEST_LOCATION); + Test::CanvasRenderer::ResetRasterizationFlag(); + + // Request rasterize manually + canvasView.RequestRasterization(); + + application.SendNotification(); + application.Render(); + + // Check if the canvasView is rasterized. + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), true, TEST_LOCATION); + Test::CanvasRenderer::ResetRasterizationFlag(); + + END_TEST; +} + +int UtcDaliCanvasViewRasterizationRequestIfRasterizeFailed01(void) +{ + tet_infoline("Test rasterization failed case for synchronous loading mode."); + ToolkitTestApplication application; + + Test::CanvasRenderer::ResetRasterizationFlag(); + + CanvasView canvasView = CanvasView::New(Vector2(300, 300)); + DALI_TEST_CHECK(canvasView); + + application.GetScene().Add(canvasView); + + canvasView.SetProperty(Actor::Property::SIZE, Vector2(300, 300)); + canvasView.SetProperty(Toolkit::CanvasView::Property::SYNCHRONOUS_LOADING, true); + canvasView.SetProperty(Toolkit::CanvasView::Property::RASTERIZATION_REQUEST_MANUALLY, true); + + Dali::CanvasRenderer::Shape shape = Dali::CanvasRenderer::Shape::New(); + + shape.AddRect(Rect(10, 10, 10, 10), Vector2(0, 0)); + + canvasView.AddDrawable(shape); + + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), false, TEST_LOCATION); + + application.SendNotification(); + application.Render(); + + // Rasterization occured + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), true, TEST_LOCATION); + Test::CanvasRenderer::ResetRasterizationFlag(); + + application.SendNotification(); + application.Render(); + + // Check whether the canvasView is not rasterized. + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), false, TEST_LOCATION); + + // Make rasterization failed. + Test::CanvasRenderer::MarkRasterizationResult(false); + + shape.AddRect(Rect(10, 10, 10, 10), Vector2(0, 0)); + + canvasView.AddDrawable(shape); + + // Request rasterize manually + canvasView.RequestRasterization(); + + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), false, TEST_LOCATION); + + application.SendNotification(); + application.Render(); + + // Check if the canvasView is rasterized. + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), true, TEST_LOCATION); + Test::CanvasRenderer::ResetRasterizationFlag(); + + application.SendNotification(); + application.Render(); + + // Check if the canvasView is rasterized again automatically. + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), true, TEST_LOCATION); + Test::CanvasRenderer::ResetRasterizationFlag(); + + application.SendNotification(); + application.Render(); + + // Check if the canvasView is rasterized again automatically. + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), true, TEST_LOCATION); + Test::CanvasRenderer::ResetRasterizationFlag(); + + // Make rasterization success. + Test::CanvasRenderer::MarkRasterizationResult(true); + + application.SendNotification(); + application.Render(); + + // Check if the canvasView is rasterized. + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), true, TEST_LOCATION); + Test::CanvasRenderer::ResetRasterizationFlag(); + + application.SendNotification(); + application.Render(); + + // Check whether the canvasView is not rasterized again. + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), false, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliCanvasViewRasterizationRequestIfRasterizeFailed02(void) +{ + tet_infoline("Test rasterization failed case for async loading mode."); + ToolkitTestApplication application; + + Test::CanvasRenderer::ResetRasterizationFlag(); + + CanvasView canvasView = CanvasView::New(Vector2(300, 300)); + DALI_TEST_CHECK(canvasView); + + application.GetScene().Add(canvasView); + + canvasView.SetProperty(Actor::Property::SIZE, Vector2(300, 300)); + canvasView.SetProperty(Toolkit::CanvasView::Property::SYNCHRONOUS_LOADING, false); + canvasView.SetProperty(Toolkit::CanvasView::Property::RASTERIZATION_REQUEST_MANUALLY, true); + + Dali::CanvasRenderer::Shape shape = Dali::CanvasRenderer::Shape::New(); + + shape.AddRect(Rect(10, 10, 10, 10), Vector2(0, 0)); + + canvasView.AddDrawable(shape); + + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), false, TEST_LOCATION); + + application.SendNotification(); + application.Render(); + + // Rasterization occured + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), true, TEST_LOCATION); + Test::CanvasRenderer::ResetRasterizationFlag(); + + application.SendNotification(); + application.Render(); + + // Check whether the canvasView is not rasterized. DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1, 0), false, TEST_LOCATION); + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), false, TEST_LOCATION); + + // Make rasterization failed. + Test::CanvasRenderer::MarkRasterizationResult(false); + + shape.AddRect(Rect(10, 10, 10, 10), Vector2(0, 0)); + + canvasView.AddDrawable(shape); // Request rasterize manually canvasView.RequestRasterization(); + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), false, TEST_LOCATION); + application.SendNotification(); application.Render(); // Check if the canvasView is rasterized. DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), true, TEST_LOCATION); + Test::CanvasRenderer::ResetRasterizationFlag(); + + application.SendNotification(); + application.Render(); + + // Check if the canvasView is rasterized again automatically. + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), true, TEST_LOCATION); + Test::CanvasRenderer::ResetRasterizationFlag(); + + application.SendNotification(); + application.Render(); + + // Check if the canvasView is rasterized again automatically. + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), true, TEST_LOCATION); + Test::CanvasRenderer::ResetRasterizationFlag(); + + // Make rasterization success. + Test::CanvasRenderer::MarkRasterizationResult(true); + + application.SendNotification(); + application.Render(); + + // Check if the canvasView is rasterized. + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), true, TEST_LOCATION); + Test::CanvasRenderer::ResetRasterizationFlag(); + + application.SendNotification(); + application.Render(); + + // Check whether the canvasView is not rasterized again. + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1, 0), false, TEST_LOCATION); + + DALI_TEST_EQUALS(Test::CanvasRenderer::IsRasterizationCalled(), false, TEST_LOCATION); + END_TEST; } diff --git a/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.cpp b/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.cpp index 1b3cae79a6..8079ba4582 100644 --- a/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.cpp +++ b/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.cpp @@ -19,6 +19,7 @@ #include "canvas-view-impl.h" // EXTERNAL INCLUDES +#include #include #include #include @@ -61,7 +62,8 @@ CanvasView::CanvasView(const Vector2& viewBox) mSize(viewBox), mIsSynchronous(true), mManualRasterization(false), - mProcessorRegistered(false) + mProcessorRegistered(false), + mLastCommitRasterized(false) { } @@ -201,25 +203,42 @@ Property::Value CanvasView::GetProperty(BaseObject* object, Property::Index prop void CanvasView::Process(bool postProcessor) { + bool rasterizeRequired = false; + mProcessorRegistered = false; - if(mCanvasRenderer && mCanvasRenderer.IsCanvasChanged() && mSize.width > 0 && mSize.height > 0) + if(mCanvasRenderer && mSize.width > 0 && mSize.height > 0) { - AddRasterizationTask(); + const bool forcibleRasterization = (mIsSynchronous && !mLastCommitRasterized); + rasterizeRequired = (forcibleRasterization) || (mCanvasRenderer.IsCanvasChanged()); + + if(rasterizeRequired) + { + AddRasterizationTask(forcibleRasterization); + } } + const bool isSynchronousRasterizationFailed = (rasterizeRequired && mIsSynchronous && !mLastCommitRasterized); + // If we are not doing manual rasterization, register processor once again. // TODO : Could we reqest it only if IsCanvasChagned() is true? - if(!mManualRasterization) + if(!mManualRasterization || isSynchronousRasterizationFailed) { RequestRasterization(); + + if(isSynchronousRasterizationFailed && DALI_LIKELY(Adaptor::IsAvailable())) + { + // To make sure we will process next time. + Adaptor::Get().RequestProcessEventsOnIdle(); + } } } -void CanvasView::AddRasterizationTask() +void CanvasView::AddRasterizationTask(bool forceProcess) { - if(mCanvasRenderer && mCanvasRenderer.Commit()) + if(mCanvasRenderer && (mCanvasRenderer.Commit() || forceProcess)) { + mLastCommitRasterized = false; if(mIsSynchronous) { CanvasRendererRasterizingTaskPtr rasterizingTask = new CanvasRendererRasterizingTask(mCanvasRenderer, MakeCallback(this, &CanvasView::ApplyRasterizedImage)); @@ -229,18 +248,24 @@ void CanvasView::AddRasterizationTask() } else { - if(!mRasterizingTask) + if(mRasterizingTask) { - mRasterizingTask = new CanvasRendererRasterizingTask(mCanvasRenderer, MakeCallback(this, &CanvasView::ApplyRasterizedImage)); - AsyncTaskManager::Get().AddTask(mRasterizingTask); + // Cancel previous request task. + AsyncTaskManager::Get().RemoveTask(mRasterizingTask); + mRasterizingTask.Reset(); } + + mRasterizingTask = new CanvasRendererRasterizingTask(mCanvasRenderer, MakeCallback(this, &CanvasView::ApplyRasterizedImage)); + AsyncTaskManager::Get().AddTask(mRasterizingTask); } } } void CanvasView::ApplyRasterizedImage(CanvasRendererRasterizingTaskPtr task) { - if(task->IsRasterized()) + mLastCommitRasterized = task->IsRasterized(); + + if(mLastCommitRasterized) { Texture rasterizedTexture = task->GetRasterizedTexture(); if(rasterizedTexture && rasterizedTexture.GetWidth() != 0 && rasterizedTexture.GetHeight() != 0) @@ -268,10 +293,10 @@ void CanvasView::ApplyRasterizedImage(CanvasRendererRasterizingTaskPtr task) mRasterizingTask.Reset(); // We don't need it anymore } - //If there are accumulated changes to CanvasRenderer during Rasterize, Rasterize once again. - if(!mIsSynchronous && !mManualRasterization && mCanvasRenderer && mCanvasRenderer.IsCanvasChanged()) + //If there are accumulated changes to CanvasRenderer during Rasterize, or previous rasterization failed, Rasterize once again. + if(!mIsSynchronous && mCanvasRenderer && (!mLastCommitRasterized || (!mManualRasterization && mCanvasRenderer.IsCanvasChanged()))) { - AddRasterizationTask(); + AddRasterizationTask(!mLastCommitRasterized); } } @@ -347,6 +372,12 @@ void CanvasView::SetRasterizationRequestManually(const bool isRasterizationManua if(!mManualRasterization) { RequestRasterization(); + + if(DALI_LIKELY(Adaptor::IsAvailable())) + { + // To make sure we will process next time. + Adaptor::Get().RequestProcessEventsOnIdle(); + } } } } diff --git a/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.h b/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.h index 82f7ff3675..563b3bfd3c 100644 --- a/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.h +++ b/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.h @@ -155,9 +155,9 @@ private: // From Control /** * @bried Rasterize the canvas, and add it to the view. * - * @param[in] size The target size of the canvas view rasterization. + * @param[in] forceProcess True if we need to rasterize forcibly without changeness check. */ - void AddRasterizationTask(); + void AddRasterizationTask(bool forceProcess); protected: /** @@ -194,6 +194,7 @@ private: bool mIsSynchronous : 1; bool mManualRasterization : 1; bool mProcessorRegistered : 1; + bool mLastCommitRasterized : 1; }; } // namespace Internal