Add async task manager 60/281660/34
authortscholb <scholb.kim@samsung.com>
Tue, 20 Sep 2022 09:03:46 +0000 (18:03 +0900)
committertscholb <scholb.kim@samsung.com>
Thu, 24 Nov 2022 09:48:54 +0000 (18:48 +0900)
Change-Id: Id9b14090fa21bdc249f826a68d260fb5d013887e

30 files changed:
automated-tests/src/dali-toolkit/utc-Dali-AsyncImageLoader.cpp
automated-tests/src/dali-toolkit/utc-Dali-CanvasView.cpp
automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp
automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp
dali-toolkit/internal/controls/canvas-view/canvas-view-impl.cpp
dali-toolkit/internal/controls/canvas-view/canvas-view-impl.h
dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-task.cpp [new file with mode: 0644]
dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-task.h [new file with mode: 0644]
dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-thread.cpp [deleted file]
dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-thread.h [deleted file]
dali-toolkit/internal/file.list
dali-toolkit/internal/helpers/round-robin-container-view.h [deleted file]
dali-toolkit/internal/image-loader/async-image-loader-impl.cpp
dali-toolkit/internal/image-loader/async-image-loader-impl.h
dali-toolkit/internal/image-loader/image-atlas-impl.cpp
dali-toolkit/internal/image-loader/loading-task.cpp [moved from dali-toolkit/internal/image-loader/image-load-thread.cpp with 60% similarity]
dali-toolkit/internal/image-loader/loading-task.h [moved from dali-toolkit/internal/image-loader/image-load-thread.h with 78% similarity]
dali-toolkit/internal/texture-manager/texture-async-loading-helper.cpp
dali-toolkit/internal/texture-manager/texture-async-loading-helper.h
dali-toolkit/internal/texture-manager/texture-manager-impl.cpp
dali-toolkit/internal/texture-manager/texture-manager-impl.h
dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.h
dali-toolkit/internal/visuals/svg/svg-rasterize-thread.cpp [deleted file]
dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h [deleted file]
dali-toolkit/internal/visuals/svg/svg-task.cpp [new file with mode: 0644]
dali-toolkit/internal/visuals/svg/svg-task.h [new file with mode: 0644]
dali-toolkit/internal/visuals/svg/svg-visual.cpp
dali-toolkit/internal/visuals/svg/svg-visual.h
dali-toolkit/internal/visuals/visual-factory-cache.cpp
dali-toolkit/internal/visuals/visual-factory-cache.h

index 067a34a..f68397d 100644 (file)
@@ -21,6 +21,7 @@
 #include <stdlib.h>
 #include <toolkit-event-thread-callback.h>
 #include <unistd.h>
+#include <dali-toolkit/devel-api/image-loader/async-image-loader-devel.h>
 
 using namespace Dali;
 using namespace Dali::Toolkit;
@@ -33,6 +34,8 @@ static const char* gImage_34_RGBA = TEST_RESOURCE_DIR "/icon-edit.png";
 static const char* gImage_50_RGBA = TEST_RESOURCE_DIR "/icon-delete.png";
 // resolution: 128*128, pixel format: RGB888
 static const char* gImage_128_RGB = TEST_RESOURCE_DIR "/gallery-small-1.jpg";
+// animated image
+static const char* gImage_gif = TEST_RESOURCE_DIR "/canvas-none.gif";
 
 // for testing the ImageLoadedSignal
 class ImageLoadedSignalVerifier : public ConnectionTracker
@@ -49,8 +52,11 @@ public:
 
   void ImageLoaded(uint32_t id, PixelData pixelData)
   {
-    mIDs.push_back(id);
-    mPixelDataList.push_back(pixelData);
+    if(pixelData)
+    {
+      mIDs.push_back(id);
+      mPixelDataList.push_back(pixelData);
+    }
     mCount++;
   }
 
@@ -210,12 +216,21 @@ int UtcDaliAsyncImageLoaderLoadAndLoadedSignal(void)
   uint32_t id02 = loader.Load(gImage_50_RGBA, ImageDimensions(25, 25));
   uint32_t id03 = loader.Load(gImage_128_RGB, ImageDimensions(100, 100), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, true);
 
-  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(3), true, TEST_LOCATION);
+  // Try load animted image
+  Dali::AnimatedImageLoading animatedImageLoading = Dali::AnimatedImageLoading::New(gImage_gif, true);
+  DevelAsyncImageLoader::LoadAnimatedImage(loader, animatedImageLoading, 0, DevelAsyncImageLoader::PreMultiplyOnLoad::OFF);
+
+  // Try apply mask image
+  Devel::PixelBuffer imageData = Devel::PixelBuffer::New(50, 50, Dali::Pixel::RGBA8888);
+  Devel::PixelBuffer maskData = Devel::PixelBuffer::New(50, 50, Dali::Pixel::RGBA8888);
+  DevelAsyncImageLoader::ApplyMask(loader, imageData, maskData, 0.0f, false, DevelAsyncImageLoader::PreMultiplyOnLoad::OFF);
+
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(4), true, TEST_LOCATION);
 
   application.SendNotification();
   application.Render();
 
-  DALI_TEST_CHECK(loadedSignalVerifier.LoadedImageCount() == 3);
+  DALI_TEST_CHECK(loadedSignalVerifier.LoadedImageCount() == 4);
   DALI_TEST_CHECK(loadedSignalVerifier.Verify(id02, 25, 25));
   DALI_TEST_CHECK(loadedSignalVerifier.Verify(id03, 100, 100));
 
@@ -223,7 +238,7 @@ int UtcDaliAsyncImageLoaderLoadAndLoadedSignal(void)
 }
 
 // Note: This is not an ideal test, but we cannot guarantee we can call Cancel() before the image has finished loading.
-int UtcDaliAsyncImageLoaderCancel(void)
+int UtcDaliAsyncImageLoaderCancel01(void)
 {
   ToolkitTestApplication application;
 
@@ -252,6 +267,19 @@ int UtcDaliAsyncImageLoaderCancel(void)
   END_TEST;
 }
 
+int UtcDaliAsyncImageLoaderCancel02(void)
+{
+  ToolkitTestApplication application;
+
+  AsyncImageLoader loader = AsyncImageLoader::New();
+  uint32_t id01 = loader.Load(gImage_34_RGBA, ImageDimensions(34, 34));
+  DALI_TEST_CHECK(loader.Cancel(id01)); // Cancle a task
+
+  application.SendNotification();
+  application.Render();
+  END_TEST;
+}
+
 int UtcDaliAsyncImageLoaderCancelAll(void)
 {
   ToolkitTestApplication application;
@@ -272,5 +300,18 @@ int UtcDaliAsyncImageLoaderCancelAll(void)
   uint32_t id = 1;
   DALI_TEST_CHECK(!(loader.Cancel(id)));
 
+  uint32_t id01 = loader.Load(gImage_34_RGBA, ImageDimensions(34, 34));
+  uint32_t id02 = loader.Load(gImage_50_RGBA, ImageDimensions(25, 25));
+  uint32_t id03 = loader.Load(gImage_128_RGB, ImageDimensions(100, 100), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, true);
+  loader.CancelAll();
+
+  // Test that cancelling a non-existing loading task will return false
+  DALI_TEST_CHECK(!(loader.Cancel(id01)));
+  DALI_TEST_CHECK(!(loader.Cancel(id02)));
+  DALI_TEST_CHECK(!(loader.Cancel(id03)));
+
+  application.SendNotification();
+  application.Render();
+
   END_TEST;
-}
+}
\ No newline at end of file
index b55622f..1a9c1db 100644 (file)
 #include <dali-toolkit/dali-toolkit.h>
 
 #include <dali-toolkit/dali-toolkit.h>
-#include <dali-toolkit/devel-api/controls/canvas-view/canvas-view.h>
-#include <dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-thread.h>
+#include <dali-toolkit/internal/controls/canvas-view/canvas-view-impl.h>
+#include <dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-task.h>
 #include <dali/devel-api/adaptor-framework/canvas-renderer/canvas-renderer-shape.h>
 #include <dali/devel-api/adaptor-framework/canvas-renderer/canvas-renderer.h>
 #include <dali/public-api/images/pixel-data.h>
+#include <dali/public-api/adaptor-framework/async-task-manager.h>
 
 using namespace Dali;
 using namespace Toolkit;
@@ -270,41 +271,13 @@ int UtcDaliCanvasViewSizeN(void)
   END_TEST;
 }
 
-int UtcDaliCanvasViewRasterizeTaskP(void)
+bool gRasterizationCompletedSignal = false;
+void rasteriztionCompleted(IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task)
 {
-  ToolkitTestApplication application;
-
-  Dali::Toolkit::Internal::CanvasView* dummyInternalCanvasView = new Dali::Toolkit::Internal::CanvasView(Vector2(100, 100));
-  DALI_TEST_CHECK(dummyInternalCanvasView);
-
-  Dali::CanvasRenderer dummyCanvasRenderer = Dali::CanvasRenderer::New(Vector2(100, 100));
-  DALI_TEST_CHECK(dummyCanvasRenderer);
-
-  IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyInternalCanvasView, dummyCanvasRenderer);
-  DALI_TEST_CHECK(task);
-
-  END_TEST;
+  gRasterizationCompletedSignal = true;
 }
 
-int UtcDaliCanvasViewRasterizeTaskGetCanvasViewP(void)
-{
-  ToolkitTestApplication application;
-
-  Dali::Toolkit::Internal::CanvasView* dummyInternalCanvasView = new Dali::Toolkit::Internal::CanvasView(Vector2(100, 100));
-  DALI_TEST_CHECK(dummyInternalCanvasView);
-
-  Dali::CanvasRenderer dummyCanvasRenderer = Dali::CanvasRenderer::New(Vector2(100, 100));
-  DALI_TEST_CHECK(dummyCanvasRenderer);
-
-  IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyInternalCanvasView, dummyCanvasRenderer);
-  DALI_TEST_CHECK(task);
-
-  DALI_TEST_EQUALS(task->GetCanvasView(), dummyInternalCanvasView, TEST_LOCATION);
-
-  END_TEST;
-}
-
-int UtcDaliCanvasViewRasterizeThreadP(void)
+int UtcDaliCanvasViewRasterizeTaskP(void)
 {
   ToolkitTestApplication application;
 
@@ -314,16 +287,13 @@ int UtcDaliCanvasViewRasterizeThreadP(void)
   Dali::CanvasRenderer dummyCanvasRenderer = Dali::CanvasRenderer::New(Vector2(100, 100));
   DALI_TEST_CHECK(dummyCanvasRenderer);
 
-  IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyInternalCanvasView, dummyCanvasRenderer);
+  IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyCanvasRenderer, MakeCallback(rasteriztionCompleted));
   DALI_TEST_CHECK(task);
 
-  Dali::Toolkit::Internal::CanvasViewRasterizeThread* dummyThread = new Dali::Toolkit::Internal::CanvasViewRasterizeThread();
-  DALI_TEST_CHECK(dummyThread);
-
   END_TEST;
 }
 
-int UtcDaliCanvasViewRasterizeThreadAddTaskP(void)
+int UtcDaliCanvasViewRasterizeTaskAddTaskP(void)
 {
   ToolkitTestApplication application;
 
@@ -333,68 +303,22 @@ int UtcDaliCanvasViewRasterizeThreadAddTaskP(void)
   Dali::CanvasRenderer dummyCanvasRenderer = Dali::CanvasRenderer::New(Vector2(100, 100));
   DALI_TEST_CHECK(dummyCanvasRenderer);
 
-  IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyInternalCanvasView, dummyCanvasRenderer);
+  IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyCanvasRenderer, MakeCallback(rasteriztionCompleted));
   DALI_TEST_CHECK(task);
 
-  IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task2 = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyInternalCanvasView, dummyCanvasRenderer);
+  IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task2 = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyCanvasRenderer, MakeCallback(rasteriztionCompleted));
   DALI_TEST_CHECK(task2);
 
-  Dali::Toolkit::Internal::CanvasViewRasterizeThread* dummyThread = new Dali::Toolkit::Internal::CanvasViewRasterizeThread();
-  DALI_TEST_CHECK(dummyThread);
-
-  dummyThread->AddTask(task);
-  dummyThread->AddTask(task2);
-
-  END_TEST;
-}
-
-int UtcDaliCanvasViewRasterizeThreadAddRemoveTaskP(void)
-{
-  ToolkitTestApplication application;
-
-  Dali::Toolkit::Internal::CanvasView* dummyInternalCanvasView = new Dali::Toolkit::Internal::CanvasView(Vector2(100, 100));
-  DALI_TEST_CHECK(dummyInternalCanvasView);
-
-  Dali::CanvasRenderer dummyCanvasRenderer = Dali::CanvasRenderer::New(Vector2(100, 100));
-  DALI_TEST_CHECK(dummyCanvasRenderer);
-
-  IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyInternalCanvasView, dummyCanvasRenderer);
-  DALI_TEST_CHECK(task);
-
-  Dali::Toolkit::Internal::CanvasViewRasterizeThread* dummyThread = new Dali::Toolkit::Internal::CanvasViewRasterizeThread();
-  DALI_TEST_CHECK(dummyThread);
-
-  dummyThread->AddTask(task);
-
-  dummyThread->RemoveTask(dummyInternalCanvasView);
-
-  END_TEST;
-}
-
-int UtcDaliCanvasViewRasterizeThreadApplyRasterizedP(void)
-{
-  ToolkitTestApplication application;
-
-  Dali::Toolkit::Internal::CanvasView* dummyInternalCanvasView = new Dali::Toolkit::Internal::CanvasView(Vector2(100, 100));
-  DALI_TEST_CHECK(dummyInternalCanvasView);
-
-  Dali::CanvasRenderer dummyCanvasRenderer = Dali::CanvasRenderer::New(Vector2(100, 100));
-  DALI_TEST_CHECK(dummyCanvasRenderer);
+  Dali::AsyncTaskManager asyncTaskManager = Dali::AsyncTaskManager::Get();
+  DALI_TEST_CHECK(asyncTaskManager);
 
-  IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyInternalCanvasView, dummyCanvasRenderer);
-  DALI_TEST_CHECK(task);
-
-  Dali::Toolkit::Internal::CanvasViewRasterizeThread* dummyThread = new Dali::Toolkit::Internal::CanvasViewRasterizeThread();
-  DALI_TEST_CHECK(dummyThread);
-
-  dummyThread->AddTask(task);
-
-  dummyThread->ApplyRasterized();
+  asyncTaskManager.AddTask(task);
+  asyncTaskManager.AddTask(task2);
 
   END_TEST;
 }
 
-int UtcDaliCanvasViewRasterizeThreadTerminateThreadP(void)
+int UtcDaliCanvasViewRasterizeTaskAddRemoveTaskP(void)
 {
   ToolkitTestApplication application;
 
@@ -404,15 +328,15 @@ int UtcDaliCanvasViewRasterizeThreadTerminateThreadP(void)
   Dali::CanvasRenderer dummyCanvasRenderer = Dali::CanvasRenderer::New(Vector2(100, 100));
   DALI_TEST_CHECK(dummyCanvasRenderer);
 
-  IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyInternalCanvasView, dummyCanvasRenderer);
+  IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyCanvasRenderer, MakeCallback(rasteriztionCompleted));
   DALI_TEST_CHECK(task);
 
-  Dali::Toolkit::Internal::CanvasViewRasterizeThread* dummyThread = new Dali::Toolkit::Internal::CanvasViewRasterizeThread();
-  DALI_TEST_CHECK(dummyThread);
+  Dali::AsyncTaskManager asyncTaskManager = Dali::AsyncTaskManager::Get();
+  DALI_TEST_CHECK(asyncTaskManager);
 
-  dummyThread->AddTask(task);
+  asyncTaskManager.AddTask(task);
 
-  Dali::Toolkit::Internal::CanvasViewRasterizeThread::TerminateThread(dummyThread);
+  asyncTaskManager.RemoveTask(task);
 
   END_TEST;
 }
@@ -427,57 +351,31 @@ PixelData CreatePixelData(unsigned int width, unsigned int height)
   return pixelData;
 }
 
-int UtcDaliCanvasViewRasterizeThreadCallProcessP(void)
-{
-  ToolkitTestApplication application;
-
-  Dali::Toolkit::Internal::CanvasView* dummyInternalCanvasView = new Dali::Toolkit::Internal::CanvasView(Vector2(100, 100));
-  DALI_TEST_CHECK(dummyInternalCanvasView);
-
-  Dali::CanvasRenderer dummyCanvasRenderer = Dali::CanvasRenderer::New(Vector2(100, 100));
-  DALI_TEST_CHECK(dummyCanvasRenderer);
-
-  IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyInternalCanvasView, dummyCanvasRenderer);
-  DALI_TEST_CHECK(task);
-
-  Dali::Toolkit::Internal::CanvasViewRasterizeThread* dummyThread = new Dali::Toolkit::Internal::CanvasViewRasterizeThread();
-  DALI_TEST_CHECK(dummyThread);
-
-  dummyThread->AddTask(task);
-
-  dummyThread->Process(false);
-
-  END_TEST;
-}
-
 int UtcDaliCanvasViewRasterizeThreadRasterizationCompletedSignalP(void)
 {
   ToolkitTestApplication application;
 
+  gRasterizationCompletedSignal = false;
+
   Dali::Toolkit::CanvasView            canvasView              = Dali::Toolkit::CanvasView::New(Vector2(100, 100));
-  Dali::Toolkit::Internal::CanvasView& dummyInternalCanvasView = GetImpl(canvasView);
 
   Dali::CanvasRenderer dummyCanvasRenderer = Dali::CanvasRenderer::New(Vector2(100, 100));
   DALI_TEST_CHECK(dummyCanvasRenderer);
 
-  IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(&dummyInternalCanvasView, dummyCanvasRenderer);
+  IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyCanvasRenderer, MakeCallback(rasteriztionCompleted));
   DALI_TEST_CHECK(task);
 
-  Dali::Toolkit::Internal::CanvasViewRasterizeThread* dummyThread = new Dali::Toolkit::Internal::CanvasViewRasterizeThread();
-  DALI_TEST_CHECK(dummyThread);
+  Dali::AsyncTaskManager asyncTaskManager = Dali::AsyncTaskManager::Get();
+  DALI_TEST_CHECK(asyncTaskManager);
 
-  dummyThread->AddTask(task);
-
-  dummyThread->Process(false);
-
-  auto texture = Texture::New(Dali::TextureType::TEXTURE_2D, Pixel::RGBA8888, 100, 100);
-
-  dummyThread->RasterizationCompletedSignal().Connect(&dummyInternalCanvasView, &Dali::Toolkit::Internal::CanvasView::ApplyRasterizedImage);
-  dummyThread->RasterizationCompletedSignal().Emit(texture);
+  asyncTaskManager.AddTask(task);
 
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
   application.SendNotification();
   application.Render();
 
+  DALI_TEST_EQUALS(gRasterizationCompletedSignal, true, TEST_LOCATION);
+
   END_TEST;
 }
 
index 5797b88..3ca8543 100644 (file)
@@ -2694,10 +2694,6 @@ void ReloadImage(ImageView imageView)
 void ResourceFailedReload(Control control)
 {
   gFailCounter++;
-  if(gFailCounter < MAX_RETRIES)
-  {
-    ReloadImage(ImageView::DownCast(control));
-  }
 }
 } // namespace
 
@@ -2716,17 +2712,14 @@ int UtcDaliImageViewReloadFailedOnResourceReadySignal(void)
 
   // loading started, this waits for the loader thread to complete
   DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
-  application.SendNotification();
-
   DALI_TEST_EQUALS(gFailCounter, 1, TEST_LOCATION);
 
+  ReloadImage(imageView);
   DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
-  application.SendNotification();
-
   DALI_TEST_EQUALS(gFailCounter, 2, TEST_LOCATION);
 
+  ReloadImage(imageView);
   DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
-  application.SendNotification();
   DALI_TEST_EQUALS(gFailCounter, 3, TEST_LOCATION);
 
   END_TEST;
@@ -3866,8 +3859,6 @@ int UtcDaliImageViewOnResourceReadySignalWithBrokenAlphaMask02(void)
     imageView.ResourceReadySignal().Connect(&OnSimpleResourceReadySignal);
 
     application.GetScene().Add(imageView);
-    application.SendNotification();
-    application.Render();
 
     // Don't unparent imageView, for keep the cache.
   };
@@ -3885,7 +3876,8 @@ int UtcDaliImageViewOnResourceReadySignalWithBrokenAlphaMask02(void)
 
   // Remain 1 signal due to we use #URL + 1 mask image.
   DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(expectResourceReadySignalCounter + 1), true, TEST_LOCATION);
-
+  application.SendNotification();
+  application.Render();
   DALI_TEST_EQUALS(gResourceReadySignalCounter, expectResourceReadySignalCounter, TEST_LOCATION);
 
   END_TEST;
@@ -4339,10 +4331,6 @@ int UtcDaliImageViewNpatchImageCacheTest02(void)
   textureCallStack.EnableLogging(true);
 
   auto TestBorderImage = [&](int index, const std::string& normalImageUrl, const Rect<int> border, const char* location) {
-    if(imageView[index])
-    {
-      imageView[index].Unparent();
-    }
     Property::Map map;
     map[Toolkit::Visual::Property::TYPE]        = Toolkit::Visual::N_PATCH;
     map[Toolkit::ImageVisual::Property::URL]    = normalImageUrl;
@@ -4375,6 +4363,7 @@ int UtcDaliImageViewNpatchImageCacheTest02(void)
 
   application.SendNotification();
   application.Render();
+
   // Check we use cached npatch data so we don't generate new texture textures
   DALI_TEST_EQUALS(textureCallStack.CountMethod("GenTextures"), 0, TEST_LOCATION);
 
index e2081c4..92e54d4 100644 (file)
@@ -1226,11 +1226,6 @@ int UtcDaliVisualFactoryGetNPatchVisual9(void)
   DALI_TEST_EQUALS(actor2.GetRendererCount(), 0u, TEST_LOCATION);
 
   application.GetScene().Add(actor2);
-
-  application.SendNotification();
-  application.Render();
-
-  application.SendNotification();
   application.Render();
 
   // Async loading is not finished yet.
index e298f10..2fff921 100644 (file)
@@ -27,7 +27,6 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/controls/control-devel.h>
-#include <dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-thread.h>
 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
@@ -57,22 +56,16 @@ CanvasView::CanvasView(const Vector2& viewBox)
   mCanvasRenderer(CanvasRenderer::New(viewBox)),
   mTexture(),
   mTextureSet(),
-  mSize(viewBox),
-  mCanvasViewRasterizeThread(nullptr)
+  mSize(viewBox)
 {
 }
 
 CanvasView::~CanvasView()
 {
-  if(mCanvasViewRasterizeThread)
-  {
-    mCanvasViewRasterizeThread->RemoveTask(this);
-
-    CanvasViewRasterizeThread::TerminateThread(mCanvasViewRasterizeThread);
-  }
-
   if(Adaptor::IsAvailable())
   {
+    Dali::AsyncTaskManager::Get().RemoveTask(mRasterizingTask);
+    mRasterizingTask.Reset();
     Adaptor::Get().UnregisterProcessor(*this, true);
   }
 }
@@ -179,40 +172,37 @@ void CanvasView::Process(bool postProcessor)
 
 void CanvasView::AddRasterizationTask()
 {
-  CanvasRendererRasterizingTaskPtr newTask = new CanvasRendererRasterizingTask(this, mCanvasRenderer);
-
-  if(!mCanvasViewRasterizeThread)
-  {
-    mCanvasViewRasterizeThread = new CanvasViewRasterizeThread();
-    mCanvasViewRasterizeThread->RasterizationCompletedSignal().Connect(this, &CanvasView::ApplyRasterizedImage);
-    mCanvasViewRasterizeThread->Start();
-  }
+  mRasterizingTask = new CanvasRendererRasterizingTask(mCanvasRenderer, MakeCallback(this, &CanvasView::ApplyRasterizedImage));
 
   if(mCanvasRenderer.Commit())
   {
-    mCanvasViewRasterizeThread->AddTask(newTask);
+    AsyncTaskManager::Get().AddTask(mRasterizingTask);
   }
 }
 
-void CanvasView::ApplyRasterizedImage(Texture rasterizedTexture)
+void CanvasView::ApplyRasterizedImage(CanvasRendererRasterizingTaskPtr task)
 {
-  if(rasterizedTexture && rasterizedTexture.GetWidth() != 0 && rasterizedTexture.GetHeight() != 0)
+  if(task->IsRasterized())
   {
-    if(!mTextureSet)
+    Texture rasterizedTexture = task->GetRasterizedTexture();
+    if(rasterizedTexture && rasterizedTexture.GetWidth() != 0 && rasterizedTexture.GetHeight() != 0)
     {
-      std::string fragmentShader = SHADER_CANVAS_VIEW_FRAG.data();
-      DevelTexture::ApplyNativeFragmentShader(rasterizedTexture, fragmentShader);
+      if(!mTextureSet)
+      {
+        std::string fragmentShader = SHADER_CANVAS_VIEW_FRAG.data();
+        DevelTexture::ApplyNativeFragmentShader(rasterizedTexture, fragmentShader);
 
-      mTextureSet       = TextureSet::New();
-      Geometry geometry = VisualFactoryCache::CreateQuadGeometry();
-      Shader   shader   = Shader::New(SHADER_CANVAS_VIEW_VERT, fragmentShader);
-      Renderer renderer = Renderer::New(geometry, shader);
+        mTextureSet       = TextureSet::New();
+        Geometry geometry = VisualFactoryCache::CreateQuadGeometry();
+        Shader   shader   = Shader::New(SHADER_CANVAS_VIEW_VERT, fragmentShader);
+        Renderer renderer = Renderer::New(geometry, shader);
 
-      renderer.SetTextures(mTextureSet);
-      renderer.SetProperty(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, true);
-      Self().AddRenderer(renderer);
+        renderer.SetTextures(mTextureSet);
+        renderer.SetProperty(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, true);
+        Self().AddRenderer(renderer);
+      }
+      mTextureSet.SetTexture(0, rasterizedTexture);
     }
-    mTextureSet.SetTexture(0, rasterizedTexture);
   }
 
   //If there are accumulated changes to CanvasRenderer during Rasterize, Rasterize once again.
index 92110f0..d7c8c4b 100644 (file)
@@ -28,6 +28,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/controls/canvas-view/canvas-view.h>
 #include <dali-toolkit/public-api/controls/control-impl.h>
+#include <dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-task.h>
 
 namespace Dali
 {
@@ -135,20 +136,20 @@ public:
   /**
    * @bried Apply the rasterized image to the canvas view
    *
-   * @param[in] rasterizedTexture The texture with the rasterized pixels
+   * @param[in] task CanvasRendererRasterizingTaskPtr
    */
-  void ApplyRasterizedImage(Texture rasterizedTexture);
+  void ApplyRasterizedImage(CanvasRendererRasterizingTaskPtr task);
 
 private:
   CanvasView(const CanvasView&) = delete;
   CanvasView& operator=(const CanvasView&) = delete;
 
 private:
-  CanvasRenderer             mCanvasRenderer;
-  Dali::Texture              mTexture;
-  TextureSet                 mTextureSet;
-  Vector2                    mSize;
-  CanvasViewRasterizeThread* mCanvasViewRasterizeThread;
+  CanvasRenderer                   mCanvasRenderer;
+  Dali::Texture                    mTexture;
+  TextureSet                       mTextureSet;
+  Vector2                          mSize;
+  CanvasRendererRasterizingTaskPtr mRasterizingTask;
 };
 
 } // namespace Internal
diff --git a/dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-task.cpp b/dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-task.cpp
new file mode 100644 (file)
index 0000000..21b4205
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ * 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.
+ *
+ */
+
+// CLASS HEADER
+#include "canvas-view-rasterize-task.h"
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+CanvasRendererRasterizingTask::CanvasRendererRasterizingTask(CanvasRenderer canvasRenderer, CallbackBase* callback)
+: AsyncTask(callback),
+  mCanvasRenderer(canvasRenderer),
+  mRasterizedSuccessed(false)
+{
+}
+
+void CanvasRendererRasterizingTask::Process()
+{
+  mRasterizedSuccessed = Rasterize();
+}
+
+bool CanvasRendererRasterizingTask::IsReady()
+{
+  return true;
+}
+
+bool CanvasRendererRasterizingTask::IsRasterized()
+{
+  return mRasterizedSuccessed;
+}
+
+bool CanvasRendererRasterizingTask::Rasterize()
+{
+  if(mCanvasRenderer && mCanvasRenderer.Rasterize())
+  {
+    return true;
+  }
+  return false;
+}
+
+Texture CanvasRendererRasterizingTask::GetRasterizedTexture()
+{
+  return mCanvasRenderer.GetRasterizedTexture();
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-task.h b/dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-task.h
new file mode 100644 (file)
index 0000000..ac375c0
--- /dev/null
@@ -0,0 +1,114 @@
+#ifndef DALI_TOOLKIT_CANVAS_VIEW_RASTERIZE_TASK_H
+#define DALI_TOOLKIT_CANVAS_VIEW_RASTERIZE_TASK_H
+
+/*
+ * 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.
+ * 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 <dali/devel-api/adaptor-framework/canvas-renderer/canvas-renderer.h>
+#include <dali/devel-api/adaptor-framework/event-thread-callback.h>
+#include <dali/devel-api/threading/conditional-wait.h>
+#include <dali/devel-api/threading/mutex.h>
+#include <dali/devel-api/threading/thread.h>
+#include <dali/integration-api/adaptor-framework/log-factory-interface.h>
+#include <dali/public-api/adaptor-framework/async-task-manager.h>
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/object/ref-object.h>
+#include <dali/public-api/rendering/texture-set.h>
+#include <memory>
+#include <vector>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+class CanvasRendererRasterizingTask;
+using CanvasRendererRasterizingTaskPtr = IntrusivePtr<CanvasRendererRasterizingTask>;
+
+/**
+ * The canvasview rasterizing tasks to be processed in the worker thread.
+ *
+ * Life cycle of a rasterizing task is as follows:
+ * 1. Created by CanvasView in the main thread
+ * 2. Queued in the worked thread waiting to be processed.
+ * 3. If this task gets its turn to do the rasterization, it triggers main thread to apply the rasterized image to material then been deleted in main thread call back.
+ *    Or if this task is been removed before its turn to be processed, it then been deleted in the worker thread.
+ */
+class CanvasRendererRasterizingTask : public AsyncTask
+{
+public:
+  /**
+   * Constructor
+   * @param[in] canvasRenderer The renderer which the rasterized canvas to be applied.
+   * @param[in] callback The callback that is called when the operation is completed.
+   */
+  CanvasRendererRasterizingTask(CanvasRenderer canvasRenderer, CallbackBase* callback);
+
+  /**
+   * Destructor.
+   */
+  ~CanvasRendererRasterizingTask() = default;
+
+  /**
+   * Process the task
+   */
+  void Process() override;
+
+  /**
+   * Whether the task is ready to process.
+   * @return True if the task is ready to process.
+   */
+  bool IsReady() override;
+
+  /**
+   * Do the rasterization with the mRasterizer.
+   * @return Returns True when it's successful. False otherwise.
+   */
+  bool Rasterize();
+
+  /**
+   * Whether the rasterize is completed
+   * @return Returns True when it's completed
+   */
+  bool IsRasterized();
+
+  /**
+   * Get the rasterization result.
+   * @return The texture with the rasterized pixels.
+   */
+  Texture GetRasterizedTexture();
+
+private:
+  // Undefined
+  CanvasRendererRasterizingTask(const CanvasRendererRasterizingTask& task);
+
+  // Undefined
+  CanvasRendererRasterizingTask& operator=(const CanvasRendererRasterizingTask& task);
+
+private:
+  CanvasRenderer mCanvasRenderer;
+  bool           mRasterizedSuccessed;
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_CANVAS_VIEW_RASTERIZE_TASK_H
diff --git a/dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-thread.cpp b/dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-thread.cpp
deleted file mode 100644 (file)
index e3de638..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (c) 2021 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.
- *
- */
-
-// CLASS HEADER
-#include "canvas-view-rasterize-thread.h"
-
-// EXTERNAL INCLUDES
-#include <dali/devel-api/adaptor-framework/thread-settings.h>
-#include <dali/integration-api/adaptor-framework/adaptor.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Internal
-{
-CanvasRendererRasterizingTask::CanvasRendererRasterizingTask(CanvasView* canvasView, CanvasRenderer canvasRenderer)
-: mCanvasView(canvasView),
-  mCanvasRenderer(canvasRenderer),
-  mRasterizedTexture()
-{
-}
-
-bool CanvasRendererRasterizingTask::Rasterize()
-{
-  if(mCanvasRenderer && mCanvasRenderer.Rasterize())
-  {
-    return true;
-  }
-  return false;
-}
-
-CanvasView* CanvasRendererRasterizingTask::GetCanvasView() const
-{
-  return mCanvasView.Get();
-}
-
-Texture CanvasRendererRasterizingTask::GetRasterizedTexture()
-{
-  return mCanvasRenderer.GetRasterizedTexture();
-}
-
-CanvasViewRasterizeThread::CanvasViewRasterizeThread()
-: mTrigger(new EventThreadCallback(MakeCallback(this, &CanvasViewRasterizeThread::ApplyRasterized))),
-  mLogFactory(Dali::Adaptor::Get().GetLogFactory()),
-  mProcessorRegistered(false),
-  mRasterizationCompletedSignal()
-{
-}
-
-CanvasViewRasterizeThread::~CanvasViewRasterizeThread()
-{
-  if(mProcessorRegistered && Adaptor::IsAvailable())
-  {
-    Adaptor::Get().UnregisterProcessor(*this);
-  }
-}
-
-void CanvasViewRasterizeThread::TerminateThread(CanvasViewRasterizeThread*& thread)
-{
-  if(thread)
-  {
-    // add an empty task would stop the thread from conditional wait.
-    thread->AddTask(CanvasRendererRasterizingTaskPtr());
-    // stop the thread
-    thread->Join();
-    // delete the thread
-    delete thread;
-    thread = NULL;
-  }
-}
-
-void CanvasViewRasterizeThread::AddTask(CanvasRendererRasterizingTaskPtr task)
-{
-  bool wasEmpty = false;
-
-  {
-    // Lock while adding task to the queue
-    ConditionalWait::ScopedLock lock(mConditionalWait);
-    wasEmpty = mRasterizeTasks.empty();
-    if(!wasEmpty && task)
-    {
-      // Remove the tasks with the same renderer.
-      // Older task which waiting to rasterize and apply the svg to the same renderer is expired.
-      for(std::vector<CanvasRendererRasterizingTaskPtr>::iterator it = mRasterizeTasks.begin(), endIt = mRasterizeTasks.end(); it != endIt; ++it)
-      {
-        if((*it) && (*it)->GetCanvasView() == task->GetCanvasView()) //Need
-        {
-          mRasterizeTasks.erase(it);
-          break;
-        }
-      }
-    }
-    mRasterizeTasks.push_back(task);
-
-    if(!mProcessorRegistered && Adaptor::IsAvailable())
-    {
-      Adaptor::Get().RegisterProcessor(*this);
-      mProcessorRegistered = true;
-    }
-  }
-
-  if(wasEmpty)
-  {
-    // wake up the image loading thread
-    mConditionalWait.Notify();
-  }
-}
-
-CanvasRendererRasterizingTaskPtr CanvasViewRasterizeThread::NextCompletedTask()
-{
-  // Lock while popping task out from the queue
-  Mutex::ScopedLock lock(mMutex);
-
-  if(mCompletedTasks.empty())
-  {
-    return CanvasRendererRasterizingTaskPtr();
-  }
-
-  std::vector<CanvasRendererRasterizingTaskPtr>::iterator next     = mCompletedTasks.begin();
-  CanvasRendererRasterizingTaskPtr                        nextTask = *next;
-  mCompletedTasks.erase(next);
-
-  return nextTask;
-}
-
-void CanvasViewRasterizeThread::RemoveTask(CanvasView* canvasView)
-{
-  // Lock while remove task from the queue
-  ConditionalWait::ScopedLock lock(mConditionalWait);
-  if(!mRasterizeTasks.empty())
-  {
-    for(std::vector<CanvasRendererRasterizingTaskPtr>::iterator it = mRasterizeTasks.begin(), endIt = mRasterizeTasks.end(); it != endIt; ++it)
-    {
-      if((*it) && (*it)->GetCanvasView() == canvasView)
-      {
-        mRasterizeTasks.erase(it);
-        break;
-      }
-    }
-  }
-
-  UnregisterProcessor();
-}
-
-CanvasRendererRasterizingTaskPtr CanvasViewRasterizeThread::NextTaskToProcess()
-{
-  // Lock while popping task out from the queue
-  ConditionalWait::ScopedLock lock(mConditionalWait);
-
-  // conditional wait
-  while(mRasterizeTasks.empty())
-  {
-    mConditionalWait.Wait(lock);
-  }
-
-  // pop out the next task from the queue
-  std::vector<CanvasRendererRasterizingTaskPtr>::iterator next     = mRasterizeTasks.begin();
-  CanvasRendererRasterizingTaskPtr                        nextTask = *next;
-  mRasterizeTasks.erase(next);
-
-  return nextTask;
-}
-
-void CanvasViewRasterizeThread::AddCompletedTask(CanvasRendererRasterizingTaskPtr task)
-{
-  // Lock while adding task to the queue
-  Mutex::ScopedLock lock(mMutex);
-  mCompletedTasks.push_back(task);
-
-  // wake up the main thread
-  mTrigger->Trigger();
-}
-
-void CanvasViewRasterizeThread::Run()
-{
-  SetThreadName("CanvasViewThread");
-  mLogFactory.InstallLogFunction();
-
-  while(CanvasRendererRasterizingTaskPtr task = NextTaskToProcess())
-  {
-    if(task->Rasterize())
-    {
-      AddCompletedTask(task);
-    }
-  }
-}
-
-void CanvasViewRasterizeThread::ApplyRasterized()
-{
-  while(CanvasRendererRasterizingTaskPtr task = NextCompletedTask())
-  {
-    RasterizationCompletedSignal().Emit(task->GetRasterizedTexture()); // Here texture get
-  }
-
-  UnregisterProcessor();
-}
-
-void CanvasViewRasterizeThread::Process(bool postProcessor)
-{
-  ApplyRasterized();
-}
-
-CanvasViewRasterizeThread::RasterizationCompletedSignalType& CanvasViewRasterizeThread::RasterizationCompletedSignal()
-{
-  return mRasterizationCompletedSignal;
-}
-
-void CanvasViewRasterizeThread::UnregisterProcessor()
-{
-  if(mProcessorRegistered)
-  {
-    if(mRasterizeTasks.empty() && mCompletedTasks.empty() && Adaptor::IsAvailable())
-    {
-      Adaptor::Get().UnregisterProcessor(*this);
-      mProcessorRegistered = false;
-    }
-  }
-}
-
-} // namespace Internal
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-thread.h b/dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-thread.h
deleted file mode 100644 (file)
index 8e96367..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-#ifndef DALI_TOOLKIT_CANVAS_VIEW_RASTERIZE_THREAD_H
-#define DALI_TOOLKIT_CANVAS_VIEW_RASTERIZE_THREAD_H
-
-/*
- * 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.
- * 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 <dali/devel-api/adaptor-framework/canvas-renderer/canvas-renderer.h>
-#include <dali/devel-api/adaptor-framework/event-thread-callback.h>
-#include <dali/devel-api/threading/conditional-wait.h>
-#include <dali/devel-api/threading/mutex.h>
-#include <dali/devel-api/threading/thread.h>
-#include <dali/integration-api/adaptor-framework/log-factory-interface.h>
-#include <dali/public-api/common/intrusive-ptr.h>
-#include <dali/public-api/object/ref-object.h>
-#include <dali/public-api/rendering/texture-set.h>
-#include <memory>
-#include <vector>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/controls/canvas-view/canvas-view-impl.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Internal
-{
-using CanvasViewPtr = IntrusivePtr<CanvasView>;
-class CanvasRendererRasterizingTask;
-using CanvasRendererRasterizingTaskPtr = IntrusivePtr<CanvasRendererRasterizingTask>;
-
-/**
- * The canvasview rasterizing tasks to be processed in the worker thread.
- *
- * Life cycle of a rasterizing task is as follows:
- * 1. Created by CanvasView in the main thread
- * 2. Queued in the worked thread waiting to be processed.
- * 3. If this task gets its turn to do the rasterization, it triggers main thread to apply the rasterized image to material then been deleted in main thread call back.
- *    Or if this task is been removed before its turn to be processed, it then been deleted in the worker thread.
- */
-class CanvasRendererRasterizingTask : public RefObject
-{
-public:
-  /**
-   * Constructor
-   * @param[in] canvasRenderer The renderer which the rasterized canvas to be applied.
-   */
-  CanvasRendererRasterizingTask(CanvasView* canvasView, CanvasRenderer canvasRenderer);
-
-  /**
-   * Destructor.
-   */
-  ~CanvasRendererRasterizingTask() = default;
-
-  /**
-   * Do the rasterization with the mRasterizer.
-   * @return Returns True when it's successful. False otherwise.
-   */
-  bool Rasterize();
-
-  /**
-   * Get the CanvasView
-   * @return The CanvasView pointer.
-   */
-  CanvasView* GetCanvasView() const;
-
-  /**
-   * Get the rasterization result.
-   * @return The texture with the rasterized pixels.
-   */
-  Texture GetRasterizedTexture();
-
-private:
-  // Undefined
-  CanvasRendererRasterizingTask(const CanvasRendererRasterizingTask& task);
-
-  // Undefined
-  CanvasRendererRasterizingTask& operator=(const CanvasRendererRasterizingTask& task);
-
-private:
-  CanvasViewPtr  mCanvasView;
-  CanvasRenderer mCanvasRenderer;
-  Texture        mRasterizedTexture;
-};
-
-/**
- * The worker thread for CanvasView rasterization.
- */
-class CanvasViewRasterizeThread : public Thread, Integration::Processor
-{
-public:
-  /// @brief ApplyRasterizedImage Event signal type
-  using RasterizationCompletedSignalType = Signal<void(Texture)>;
-
-public:
-  /**
-   * Constructor.
-   *
-   * @param[in] trigger The trigger to wake up the main thread.
-   */
-  CanvasViewRasterizeThread();
-
-  /**
-   * Terminate the CanvasView rasterize thread, join and delete.
-   *
-   * @param[in] thread The rasterize thread.
-   */
-  static void TerminateThread(CanvasViewRasterizeThread*& thread);
-
-  /**
-   * Add a rasterization task into the waiting queue, called by main thread.
-   *
-   * @param[in] task The task added to the queue.
-   */
-  void AddTask(CanvasRendererRasterizingTaskPtr task);
-
-  /**
-   * Remove the task with the given CanvasView from the waiting queue, called by main thread.
-   *
-   * Typically called when the actor is put off stage, so the renderer is not needed anymore.
-   *
-   * @param[in] canvasView The CanvasView pointer.
-   */
-  void RemoveTask(CanvasView* canvasView);
-
-  /**
-   * Applies the rasterized image to material
-   */
-  void ApplyRasterized();
-
-  /**
-   * @copydoc Dali::Integration::Processor::Process()
-   */
-  void Process(bool postProcessor) override;
-
-  /**
-   * @brief This signal is emitted when rasterized image is applied.
-   *
-   * @return The signal to connect to
-   */
-  RasterizationCompletedSignalType& RasterizationCompletedSignal();
-
-private:
-  /**
-   * Pop the next task out from the queue.
-   *
-   * @return The next task to be processed.
-   */
-  CanvasRendererRasterizingTaskPtr NextTaskToProcess();
-
-  /**
-   * Pop the next task out from the completed queue, called by main thread.
-   *
-   * @return The next task in the completed queue.
-   */
-  CanvasRendererRasterizingTaskPtr NextCompletedTask();
-
-  /**
-   * Add a task in to the queue
-   *
-   * @param[in] task The task added to the queue.
-   */
-  void AddCompletedTask(CanvasRendererRasterizingTaskPtr task);
-
-  /**
-   * @brief Unregister a previously registered processor
-   *
-   */
-  void UnregisterProcessor();
-
-protected:
-  /**
-   * Destructor.
-   */
-  ~CanvasViewRasterizeThread() override;
-
-  /**
-   * The entry function of the worker thread.
-   * It fetches task from the Queue, rasterizes the image and apply to the renderer.
-   */
-  void Run() override;
-
-private:
-  // Undefined
-  CanvasViewRasterizeThread(const CanvasViewRasterizeThread& thread);
-
-  // Undefined
-  CanvasViewRasterizeThread& operator=(const CanvasViewRasterizeThread& thread);
-
-private:
-  std::vector<CanvasRendererRasterizingTaskPtr> mRasterizeTasks; //The queue of the tasks waiting to rasterize the CanvasView.
-  std::vector<CanvasRendererRasterizingTaskPtr> mCompletedTasks; //The queue of the tasks with the SVG rasterization completed
-
-  ConditionalWait                      mConditionalWait;
-  Dali::Mutex                          mMutex;
-  std::unique_ptr<EventThreadCallback> mTrigger;
-  const Dali::LogFactoryInterface&     mLogFactory;
-  bool                                 mProcessorRegistered;
-  RasterizationCompletedSignalType     mRasterizationCompletedSignal;
-};
-
-} // namespace Internal
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_CANVAS_VIEW_RASTERIZE_THREAD_H
index ac79b42..698d8a4 100644 (file)
@@ -42,7 +42,7 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/visuals/npatch-loader.cpp
    ${toolkit_src_dir}/visuals/npatch/npatch-visual.cpp
    ${toolkit_src_dir}/visuals/primitive/primitive-visual.cpp
-   ${toolkit_src_dir}/visuals/svg/svg-rasterize-thread.cpp
+   ${toolkit_src_dir}/visuals/svg/svg-task.cpp
    ${toolkit_src_dir}/visuals/svg/svg-visual.cpp
    ${toolkit_src_dir}/visuals/text-visual-shader-factory.cpp
    ${toolkit_src_dir}/visuals/text/text-visual.cpp
@@ -65,7 +65,7 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/controls/buttons/radio-button-impl.cpp
    ${toolkit_src_dir}/controls/buttons/toggle-button-impl.cpp
    ${toolkit_src_dir}/controls/canvas-view/canvas-view-impl.cpp
-   ${toolkit_src_dir}/controls/canvas-view/canvas-view-rasterize-thread.cpp
+   ${toolkit_src_dir}/controls/canvas-view/canvas-view-rasterize-task.cpp
    ${toolkit_src_dir}/controls/control/control-data-impl.cpp
    ${toolkit_src_dir}/controls/control/control-debug.cpp
    ${toolkit_src_dir}/controls/control/control-renderers.cpp
@@ -124,9 +124,7 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/controls/gl-view/gl-view-impl.cpp
    ${toolkit_src_dir}/controls/gl-view/gl-view-render-thread.cpp
    ${toolkit_src_dir}/accessibility-manager/accessibility-manager-impl.cpp
-
    ${toolkit_src_dir}/feedback/feedback-style.cpp
-
    ${toolkit_src_dir}/focus-manager/keyboard-focus-manager-impl.cpp
    ${toolkit_src_dir}/focus-manager/keyinput-focus-manager-impl.cpp
    ${toolkit_src_dir}/helpers/color-conversion.cpp
@@ -138,7 +136,7 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/image-loader/async-image-loader-impl.cpp
    ${toolkit_src_dir}/image-loader/atlas-packer.cpp
    ${toolkit_src_dir}/image-loader/image-atlas-impl.cpp
-   ${toolkit_src_dir}/image-loader/image-load-thread.cpp
+   ${toolkit_src_dir}/image-loader/loading-task.cpp
    ${toolkit_src_dir}/image-loader/image-url-impl.cpp
    ${toolkit_src_dir}/styling/style-manager-impl.cpp
    ${toolkit_src_dir}/text/abstract-style-character-run.cpp
diff --git a/dali-toolkit/internal/helpers/round-robin-container-view.h b/dali-toolkit/internal/helpers/round-robin-container-view.h
deleted file mode 100644 (file)
index 5a5f07c..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-
-#ifndef DALI_TOOLKIT_INTERNAL_ROUND_ROBIN_CONTAINER_VIEW_H
-#define DALI_TOOLKIT_INTERNAL_ROUND_ROBIN_CONTAINER_VIEW_H
-
-/*
- * 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.
- * 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 <cstddef>
-#include <vector>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Internal
-{
-/**
- * @brief RoundRobinContainerView is a view to a container that allows iterating through the elements cyclically.
- */
-template<typename T>
-class RoundRobinContainerView
-{
-public:
-  using ContainerType = std::vector<T>;
-
-  /**
-   * @brief Constructs a new RoundRobinControlView with the given number elements using the provided factory.
-   * @param[in] numberOfElements The number of elements in the container
-   * @param[in] factory          Factory function of functor that will be used to create instances of the elements
-   */
-  template<typename FactoryType>
-  RoundRobinContainerView(size_t numberOfElements, const FactoryType& factory)
-  : mElements(),
-    mNextIndex{}
-  {
-    mElements.reserve(numberOfElements);
-    for(unsigned i = {}; i < numberOfElements; ++i)
-    {
-      mElements.push_back(factory());
-    }
-  }
-
-  /**
-   * @brief Clear all elements.
-   */
-  void Clear()
-  {
-    mElements.clear();
-  }
-
-  /**
-   * @brief Reset the position of the iterator returned by GetNext() to the first element.
-   */
-  void Reset()
-  {
-    mNextIndex = 0u;
-  }
-
-  /**
-   * @brief Returns the next element on the container.
-   * @return Iterator for the next element
-   */
-  typename ContainerType::iterator GetNext()
-  {
-    SetValidNextIndex();
-
-    return mElements.begin() + mNextIndex++;
-  }
-
-  /**
-   * @brief Returns the iterator to the end of the container.
-   *
-   * Can be used to compare against GetNext() to check if the container is empty.
-   *
-   * @return The container end() element
-   */
-  typename ContainerType::const_iterator End() const
-  {
-    return mElements.cend();
-  }
-
-  /**
-   * @brief Returns the element count.
-   * @return The element count
-   */
-  size_t GetElementCount() const
-  {
-    return mElements.size();
-  }
-
-  // default members
-  ~RoundRobinContainerView() = default;
-
-  RoundRobinContainerView(const RoundRobinContainerView&) = delete;
-  RoundRobinContainerView& operator=(const RoundRobinContainerView&) = delete;
-  RoundRobinContainerView(RoundRobinContainerView&&)                 = default;
-  RoundRobinContainerView& operator=(RoundRobinContainerView&&) = default;
-
-private:
-  /**
-   * @brief Check the current index and reset if necessary.
-   */
-  void SetValidNextIndex()
-  {
-    if(mNextIndex >= mElements.size())
-    {
-      Reset();
-    }
-  }
-
-private:
-  ContainerType mElements;  //< container of elements
-  size_t        mNextIndex; //< index to the next element to be viewed
-};
-
-} // namespace Internal
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_INTERNAL_ROUND_ROBIN_CONTAINER_VIEW_H
index 880db04..7ce566e 100644 (file)
@@ -19,6 +19,7 @@
 #include "async-image-loader-impl.h"
 
 // EXTERNAL INCLUDES
+#include <dali/public-api/adaptor-framework/async-task-manager.h>
 #include <dali/integration-api/adaptor-framework/adaptor.h>
 
 namespace Dali
@@ -29,15 +30,13 @@ namespace Internal
 {
 AsyncImageLoader::AsyncImageLoader()
 : mLoadedSignal(),
-  mLoadThread(new EventThreadCallback(MakeCallback(this, &AsyncImageLoader::ProcessLoadedImage))),
-  mLoadTaskId(0u),
-  mIsLoadThreadStarted(false)
+  mLoadTaskId(0u)
 {
 }
 
 AsyncImageLoader::~AsyncImageLoader()
 {
-  mLoadThread.CancelAll();
+  CancelAll();
 }
 
 IntrusivePtr<AsyncImageLoader> AsyncImageLoader::New()
@@ -50,13 +49,8 @@ uint32_t AsyncImageLoader::LoadAnimatedImage(Dali::AnimatedImageLoading
                                              uint32_t                                 frameIndex,
                                              DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
 {
-  if(!mIsLoadThreadStarted)
-  {
-    mLoadThread.Start();
-    mIsLoadThreadStarted = true;
-  }
-  mLoadThread.AddTask(new LoadingTask(++mLoadTaskId, animatedImageLoading, frameIndex, preMultiplyOnLoad));
-
+  LoadingTaskPtr loadingTask = new LoadingTask(++mLoadTaskId, animatedImageLoading, frameIndex, preMultiplyOnLoad,MakeCallback(this, &AsyncImageLoader::ProcessLoadedImage));
+  Dali::AsyncTaskManager::Get().AddTask(loadingTask);
   return mLoadTaskId;
 }
 
@@ -68,13 +62,9 @@ uint32_t AsyncImageLoader::Load(const VisualUrl&                         url,
                                 DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad,
                                 bool                                     loadPlanes)
 {
-  if(!mIsLoadThreadStarted)
-  {
-    mLoadThread.Start();
-    mIsLoadThreadStarted = true;
-  }
-  mLoadThread.AddTask(new LoadingTask(++mLoadTaskId, url, dimensions, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad, loadPlanes));
-
+  LoadingTaskPtr loadingTask = new LoadingTask(++mLoadTaskId, url, dimensions, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad, loadPlanes, MakeCallback(this, &AsyncImageLoader::ProcessLoadedImage));
+  AsyncTaskManager::Get().AddTask(loadingTask);
+  mLoadingTasks.push_back(AsyncImageLoadingInfo(loadingTask,mLoadTaskId));
   return mLoadTaskId;
 }
 
@@ -85,13 +75,9 @@ uint32_t AsyncImageLoader::LoadEncodedImageBuffer(const EncodedImageBuffer&
                                                   bool                                     orientationCorrection,
                                                   DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
 {
-  if(!mIsLoadThreadStarted)
-  {
-    mLoadThread.Start();
-    mIsLoadThreadStarted = true;
-  }
-  mLoadThread.AddTask(new LoadingTask(++mLoadTaskId, encodedImageBuffer, dimensions, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad));
-
+  LoadingTaskPtr loadingTask = new LoadingTask(++mLoadTaskId, encodedImageBuffer, dimensions, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad, MakeCallback(this, &AsyncImageLoader::ProcessLoadedImage));
+  Dali::AsyncTaskManager::Get().AddTask(loadingTask);
+  mLoadingTasks.push_back(AsyncImageLoadingInfo(loadingTask,mLoadTaskId));
   return mLoadTaskId;
 }
 
@@ -101,13 +87,9 @@ uint32_t AsyncImageLoader::ApplyMask(Devel::PixelBuffer                       pi
                                      bool                                     cropToMask,
                                      DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
 {
-  if(!mIsLoadThreadStarted)
-  {
-    mLoadThread.Start();
-    mIsLoadThreadStarted = true;
-  }
-  mLoadThread.AddTask(new LoadingTask(++mLoadTaskId, pixelBuffer, maskPixelBuffer, contentScale, cropToMask, preMultiplyOnLoad));
-
+  LoadingTaskPtr loadingTask = new LoadingTask(++mLoadTaskId, pixelBuffer, maskPixelBuffer, contentScale, cropToMask, preMultiplyOnLoad, MakeCallback(this, &AsyncImageLoader::ProcessLoadedImage));
+  Dali::AsyncTaskManager::Get().AddTask(loadingTask);
+  mLoadingTasks.push_back(AsyncImageLoadingInfo(loadingTask,mLoadTaskId));
   return mLoadTaskId;
 }
 
@@ -123,33 +105,73 @@ Toolkit::DevelAsyncImageLoader::PixelBufferLoadedSignalType& AsyncImageLoader::P
 
 bool AsyncImageLoader::Cancel(uint32_t loadingTaskId)
 {
-  return mLoadThread.CancelTask(loadingTaskId);
+  // Remove already completed tasks
+  RemoveCompletedTask();
+
+  auto end = mLoadingTasks.end();
+  for(std::vector<AsyncImageLoadingInfo>::iterator iter = mLoadingTasks.begin(); iter != end; ++iter)
+  {
+    if((*iter).loadId == loadingTaskId)
+    {
+      Dali::AsyncTaskManager::Get().RemoveTask((*iter).loadingTask);
+      mLoadingTasks.erase(iter);
+      return true;
+    }
+  }
+
+  return false;
 }
 
 void AsyncImageLoader::CancelAll()
 {
-  mLoadThread.CancelAll();
+  // Remove already completed tasks
+  RemoveCompletedTask();
+
+  auto end = mLoadingTasks.end();
+  for(std::vector<AsyncImageLoadingInfo>::iterator iter = mLoadingTasks.begin(); iter != end; ++iter)
+  {
+    if((*iter).loadingTask && Dali::AsyncTaskManager::Get())
+    {
+      Dali::AsyncTaskManager::Get().RemoveTask(((*iter).loadingTask));
+    }
+  }
+  mLoadingTasks.clear();
 }
 
-void AsyncImageLoader::ProcessLoadedImage()
+void AsyncImageLoader::ProcessLoadedImage(LoadingTaskPtr task)
 {
-  while(LoadingTask* next = mLoadThread.NextCompletedTask())
+  if(mPixelBufferLoadedSignal.GetConnectionCount() > 0)
+  {
+    mPixelBufferLoadedSignal.Emit(task->id, task->pixelBuffers);
+  }
+  else if(mLoadedSignal.GetConnectionCount() > 0)
   {
-    if(mPixelBufferLoadedSignal.GetConnectionCount() > 0)
+    PixelData pixelData;
+    if(!task->pixelBuffers.empty())
     {
-      mPixelBufferLoadedSignal.Emit(next->id, next->pixelBuffers);
+      pixelData = Devel::PixelBuffer::Convert(task->pixelBuffers[0]);
     }
-    else if(mLoadedSignal.GetConnectionCount() > 0)
+    mLoadedSignal.Emit(task->id, pixelData);
+  }
+
+  mCompletedTaskIds.push_back(task->id);
+}
+
+void AsyncImageLoader::RemoveCompletedTask()
+{
+  std::uint32_t loadingTaskId;
+  auto end = mLoadingTasks.end();
+  auto endCompletedIter = mCompletedTaskIds.end();
+  for(std::vector<AsyncImageLoadingInfo>::iterator iter = mLoadingTasks.begin(); iter != end; ++iter)
+  {
+    loadingTaskId = (*iter).loadId;
+    for(auto iterCompleted = mCompletedTaskIds.begin(); iterCompleted != endCompletedIter; ++iterCompleted)
     {
-      PixelData pixelData;
-      if(!next->pixelBuffers.empty())
+      if((*iterCompleted) == loadingTaskId)
       {
-        pixelData = Devel::PixelBuffer::Convert(next->pixelBuffers[0]);
+        mLoadingTasks.erase(iter);
       }
-      mLoadedSignal.Emit(next->id, pixelData);
     }
-
-    delete next;
   }
 }
 
index 34496b1..a75fa32 100644 (file)
@@ -23,7 +23,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/image-loader/async-image-loader-devel.h>
-#include <dali-toolkit/internal/image-loader/image-load-thread.h>
+#include <dali-toolkit/internal/image-loader/loading-task.h>
 #include <dali-toolkit/public-api/image-loader/async-image-loader.h>
 
 namespace Dali
@@ -32,7 +32,21 @@ namespace Toolkit
 {
 namespace Internal
 {
-class AsyncImageLoader : public BaseObject
+using LoadingTaskPtr = IntrusivePtr<LoadingTask>;
+
+struct AsyncImageLoadingInfo
+{
+  AsyncImageLoadingInfo(LoadingTaskPtr loadingTask,std::uint32_t loadId)
+  : loadingTask(loadingTask),
+    loadId(loadId)
+  {
+  }
+
+  LoadingTaskPtr loadingTask;
+  std::uint32_t  loadId;
+};
+
+class AsyncImageLoader : public BaseObject, public ConnectionTracker
 {
 public:
   /**
@@ -126,7 +140,7 @@ public:
   /**
    * Process the completed loading task from the worker thread.
    */
-  void ProcessLoadedImage();
+  void ProcessLoadedImage(LoadingTaskPtr task);
 
 protected:
   /**
@@ -135,12 +149,17 @@ protected:
   ~AsyncImageLoader() override;
 
 private:
+  /**
+   * Remove already completed tasks
+   */
+  void RemoveCompletedTask();
+
+private:
   Toolkit::AsyncImageLoader::ImageLoadedSignalType            mLoadedSignal;
   Toolkit::DevelAsyncImageLoader::PixelBufferLoadedSignalType mPixelBufferLoadedSignal;
-
-  ImageLoadThread mLoadThread;
-  uint32_t        mLoadTaskId;
-  bool            mIsLoadThreadStarted;
+  std::vector<AsyncImageLoadingInfo>                          mLoadingTasks;
+  std::vector<uint32_t>                                       mCompletedTaskIds;
+  uint32_t                                                    mLoadTaskId;
 };
 
 } // namespace Internal
index be946ab..2e86294 100644 (file)
@@ -89,6 +89,12 @@ ImageAtlas::ImageAtlas(SizeType width, SizeType height, Pixel::Format pixelForma
 
 ImageAtlas::~ImageAtlas()
 {
+  if(mAsyncLoader)
+  {
+    mAsyncLoader.CancelAll();
+    mAsyncLoader.ImageLoadedSignal().Disconnect(this, &ImageAtlas::UploadToAtlas);
+  }
+
   const std::size_t count = mLoadingTaskInfoContainer.Count();
   for(std::size_t i = 0; i < count; ++i)
   {
@@ -211,6 +217,7 @@ bool ImageAtlas::Upload(Vector4&                  textureRect,
   {
     uint32_t loadId = GetImplementation(mAsyncLoader).LoadEncodedImageBuffer(encodedImageBuffer, size, fittingMode, SamplingMode::BOX_THEN_LINEAR, orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad::OFF);
     mLoadingTaskInfoContainer.PushBack(new LoadingTaskInfo(loadId, packPositionX, packPositionY, size.GetWidth(), size.GetHeight(), atlasUploadObserver));
+
     // apply the half pixel correction
     textureRect.x = (static_cast<float>(packPositionX) + 0.5f) / mWidth;                // left
     textureRect.y = (static_cast<float>(packPositionY) + 0.5f) / mHeight;               // top
@@ -273,37 +280,42 @@ void ImageAtlas::ObserverDestroyed(AtlasUploadObserver* observer)
 
 void ImageAtlas::UploadToAtlas(uint32_t id, PixelData pixelData)
 {
-  if(mLoadingTaskInfoContainer[0]->loadTaskId == id)
+  auto end = mLoadingTaskInfoContainer.End();
+  for(auto loadingTaskIterator = mLoadingTaskInfoContainer.Begin(); loadingTaskIterator != end; ++loadingTaskIterator)
   {
-    Rect<uint32_t> packRect(mLoadingTaskInfoContainer[0]->packRect);
-    if(!pixelData || (pixelData.GetWidth() == 0 && pixelData.GetHeight() == 0))
+    if((*loadingTaskIterator) && (*loadingTaskIterator)->loadTaskId == id)
     {
-      if(!mBrokenImageUrl.empty()) // replace with the broken image
+      Rect<uint32_t> packRect((*loadingTaskIterator)->packRect);
+      if(!pixelData || (pixelData.GetWidth() == 0 && pixelData.GetHeight() == 0))
       {
-        UploadBrokenImage(packRect);
+        if(!mBrokenImageUrl.empty()) // replace with the broken image
+        {
+          UploadBrokenImage(packRect);
+        }
       }
-    }
-    else
-    {
-      if(pixelData.GetWidth() < packRect.width || pixelData.GetHeight() < packRect.height)
+      else
       {
-        DALI_LOG_ERROR("Can not upscale the image from actual loaded size [ %d, %d ] to specified size [ %d, %d ]\n",
-                       pixelData.GetWidth(),
-                       pixelData.GetHeight(),
-                       packRect.width,
-                       packRect.height);
+        if(pixelData.GetWidth() < packRect.width || pixelData.GetHeight() < packRect.height)
+        {
+          DALI_LOG_ERROR("Can not upscale the image from actual loaded size [ %d, %d ] to specified size [ %d, %d ]\n",
+                        pixelData.GetWidth(),
+                        pixelData.GetHeight(),
+                        packRect.width,
+                        packRect.height);
+        }
+
+        mAtlas.Upload(pixelData, 0u, 0u, packRect.x, packRect.y, packRect.width, packRect.height);
       }
 
-      mAtlas.Upload(pixelData, 0u, 0u, packRect.x, packRect.y, packRect.width, packRect.height);
-    }
+      if((*loadingTaskIterator)->observer)
+      {
+        (*loadingTaskIterator)->observer->UploadCompleted();
+        (*loadingTaskIterator)->observer->Unregister(*this);
+      }
 
-    if(mLoadingTaskInfoContainer[0]->observer)
-    {
-      mLoadingTaskInfoContainer[0]->observer->UploadCompleted();
-      mLoadingTaskInfoContainer[0]->observer->Unregister(*this);
+      mLoadingTaskInfoContainer.Erase(loadingTaskIterator);
+      break;
     }
-
-    mLoadingTaskInfoContainer.Erase(mLoadingTaskInfoContainer.Begin());
   }
 }
 
@@ -16,7 +16,7 @@
  */
 
 // CLASS HEADER
-#include "image-load-thread.h"
+#include "loading-task.h"
 
 // EXTERNAL INCLUDES
 #include <dali/devel-api/adaptor-framework/image-loading.h>
@@ -31,10 +31,12 @@ namespace Toolkit
 {
 namespace Internal
 {
-LoadingTask::LoadingTask(uint32_t id, Dali::AnimatedImageLoading animatedImageLoading, uint32_t frameIndex, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
-: url(),
+LoadingTask::LoadingTask(uint32_t id, Dali::AnimatedImageLoading animatedImageLoading, uint32_t frameIndex, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad, CallbackBase* callback)
+: AsyncTask(callback),
+  url(),
   encodedImageBuffer(),
   id(id),
+  textureId(TextureManagerType::INVALID_TEXTURE_ID),
   dimensions(),
   fittingMode(),
   samplingMode(),
@@ -46,14 +48,17 @@ LoadingTask::LoadingTask(uint32_t id, Dali::AnimatedImageLoading animatedImageLo
   orientationCorrection(),
   isMaskTask(false),
   cropToMask(false),
-  loadPlanes(false)
+  loadPlanes(false),
+  isReady(true)
 {
 }
 
-LoadingTask::LoadingTask(uint32_t id, const VisualUrl& url, ImageDimensions dimensions, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad, bool loadPlanes)
-: url(url),
+LoadingTask::LoadingTask(uint32_t id, const VisualUrl& url, ImageDimensions dimensions, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad, bool loadPlanes, CallbackBase* callback)
+: AsyncTask(callback),
+  url(url),
   encodedImageBuffer(),
   id(id),
+  textureId(TextureManagerType::INVALID_TEXTURE_ID),
   dimensions(dimensions),
   fittingMode(fittingMode),
   samplingMode(samplingMode),
@@ -65,14 +70,17 @@ LoadingTask::LoadingTask(uint32_t id, const VisualUrl& url, ImageDimensions dime
   orientationCorrection(orientationCorrection),
   isMaskTask(false),
   cropToMask(false),
-  loadPlanes(loadPlanes)
+  loadPlanes(loadPlanes),
+  isReady(true)
 {
 }
 
-LoadingTask::LoadingTask(uint32_t id, const EncodedImageBuffer& encodedImageBuffer, ImageDimensions dimensions, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
-: url(),
+LoadingTask::LoadingTask(uint32_t id, const EncodedImageBuffer& encodedImageBuffer, ImageDimensions dimensions, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad, CallbackBase* callback)
+: AsyncTask(callback),
+  url(),
   encodedImageBuffer(encodedImageBuffer),
   id(id),
+  textureId(TextureManagerType::INVALID_TEXTURE_ID),
   dimensions(dimensions),
   fittingMode(fittingMode),
   samplingMode(samplingMode),
@@ -84,14 +92,17 @@ LoadingTask::LoadingTask(uint32_t id, const EncodedImageBuffer& encodedImageBuff
   orientationCorrection(orientationCorrection),
   isMaskTask(false),
   cropToMask(false),
-  loadPlanes(false)
+  loadPlanes(false),
+  isReady(true)
 {
 }
 
-LoadingTask::LoadingTask(uint32_t id, Devel::PixelBuffer pixelBuffer, Devel::PixelBuffer maskPixelBuffer, float contentScale, bool cropToMask, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
-: url(""),
+LoadingTask::LoadingTask(uint32_t id, Devel::PixelBuffer pixelBuffer, Devel::PixelBuffer maskPixelBuffer, float contentScale, bool cropToMask, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad, CallbackBase* callback)
+: AsyncTask(callback),
+  url(""),
   encodedImageBuffer(),
   id(id),
+  textureId(TextureManagerType::INVALID_TEXTURE_ID),
   dimensions(),
   fittingMode(),
   samplingMode(),
@@ -103,11 +114,36 @@ LoadingTask::LoadingTask(uint32_t id, Devel::PixelBuffer pixelBuffer, Devel::Pix
   orientationCorrection(),
   isMaskTask(true),
   cropToMask(cropToMask),
-  loadPlanes(false)
+  loadPlanes(false),
+  isReady(true)
 {
   pixelBuffers.push_back(pixelBuffer);
 }
 
+LoadingTask::~LoadingTask()
+{
+}
+
+void LoadingTask::Process()
+{
+  isReady = false;
+  if(!isMaskTask)
+  {
+    Load();
+  }
+  else
+  {
+    ApplyMask();
+  }
+  MultiplyAlpha();
+  isReady = true;
+}
+
+bool LoadingTask::IsReady()
+{
+  return isReady;
+}
+
 void LoadingTask::Load()
 {
   Devel::PixelBuffer pixelBuffer;
@@ -165,144 +201,9 @@ void LoadingTask::MultiplyAlpha()
   }
 }
 
-ImageLoadThread::ImageLoadThread(EventThreadCallback* trigger)
-: mTrigger(trigger),
-  mLogFactory(Dali::Adaptor::Get().GetLogFactory())
-{
-}
-
-ImageLoadThread::~ImageLoadThread()
-{
-  // add an empty task would stop the thread from conditional wait.
-  AddTask(NULL);
-  // stop the thread
-  Join();
-
-  delete mTrigger;
-
-  for(auto&& iter : mLoadQueue)
-  {
-    delete iter;
-  }
-  mLoadQueue.Clear();
-
-  for(auto&& iter : mCompleteQueue)
-  {
-    delete iter;
-  }
-  mCompleteQueue.Clear();
-}
-
-void ImageLoadThread::Run()
-{
-  SetThreadName("ImageLoadThread");
-  mLogFactory.InstallLogFunction();
-
-  while(LoadingTask* task = NextTaskToProcess())
-  {
-    if(!task->isMaskTask)
-    {
-      task->Load();
-    }
-    else
-    {
-      task->ApplyMask();
-    }
-    task->MultiplyAlpha();
-
-    AddCompletedTask(task);
-  }
-}
-
-void ImageLoadThread::AddTask(LoadingTask* task)
-{
-  bool wasEmpty = false;
-  {
-    // Lock while adding task to the queue
-    ConditionalWait::ScopedLock lock(mConditionalWait);
-    wasEmpty = mLoadQueue.Empty();
-    mLoadQueue.PushBack(task);
-  }
-
-  if(wasEmpty)
-  {
-    // wake up the image loading thread
-    mConditionalWait.Notify();
-  }
-}
-
-LoadingTask* ImageLoadThread::NextCompletedTask()
-{
-  // Lock while popping task out from the queue
-  Mutex::ScopedLock lock(mMutex);
-
-  if(mCompleteQueue.Empty())
-  {
-    return NULL;
-  }
-
-  Vector<LoadingTask*>::Iterator next     = mCompleteQueue.Begin();
-  LoadingTask*                   nextTask = *next;
-  mCompleteQueue.Erase(next);
-
-  return nextTask;
-}
-
-bool ImageLoadThread::CancelTask(uint32_t loadingTaskId)
-{
-  // Lock while remove task from the queue
-  ConditionalWait::ScopedLock lock(mConditionalWait);
-
-  for(Vector<LoadingTask*>::Iterator iter = mLoadQueue.Begin(); iter != mLoadQueue.End(); ++iter)
-  {
-    if((*iter)->id == loadingTaskId)
-    {
-      delete(*iter);
-      mLoadQueue.Erase(iter);
-      return true;
-    }
-  }
-
-  return false;
-}
-
-void ImageLoadThread::CancelAll()
-{
-  // Lock while remove task from the queue
-  ConditionalWait::ScopedLock lock(mConditionalWait);
-
-  for(Vector<LoadingTask*>::Iterator iter = mLoadQueue.Begin(); iter != mLoadQueue.End(); ++iter)
-  {
-    delete(*iter);
-  }
-  mLoadQueue.Clear();
-}
-
-LoadingTask* ImageLoadThread::NextTaskToProcess()
+void LoadingTask::SetTextureId(TextureManagerType::TextureId id)
 {
-  // Lock while popping task out from the queue
-  ConditionalWait::ScopedLock lock(mConditionalWait);
-
-  while(mLoadQueue.Empty())
-  {
-    mConditionalWait.Wait(lock);
-  }
-
-  Vector<LoadingTask*>::Iterator next     = mLoadQueue.Begin();
-  LoadingTask*                   nextTask = *next;
-  mLoadQueue.Erase(next);
-
-  return nextTask;
-}
-
-void ImageLoadThread::AddCompletedTask(LoadingTask* task)
-{
-  // Lock while adding task to the queue
-  Mutex::ScopedLock lock(mMutex);
-  mCompleteQueue.PushBack(task);
-
-  // wake up the main thread
-  mTrigger->Trigger();
+  textureId = id;
 }
 
 } // namespace Internal
@@ -1,5 +1,5 @@
-#ifndef DALI_TOOLKIT_IMAGE_LOAD_THREAD_H
-#define DALI_TOOLKIT_IMAGE_LOAD_THREAD_H
+#ifndef DALI_TOOLKIT_IMAGE_LOADING_TASK_H
+#define DALI_TOOLKIT_IMAGE_LOADING_TASK_H
 
 /*
  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
@@ -20,6 +20,7 @@
 // EXTERNAL INCLUDES
 #include <dali-toolkit/devel-api/image-loader/async-image-loader-devel.h>
 #include <dali-toolkit/internal/visuals/visual-url.h>
+#include <dali/public-api/adaptor-framework/async-task-manager.h>
 #include <dali/devel-api/adaptor-framework/event-thread-callback.h>
 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
 #include <dali/devel-api/threading/conditional-wait.h>
@@ -30,6 +31,7 @@
 #include <dali/public-api/common/dali-vector.h>
 #include <dali/public-api/images/image-operations.h>
 #include <dali/public-api/object/ref-object.h>
+#include <dali-toolkit/internal/texture-manager/texture-manager-type.h>
 
 namespace Dali
 {
@@ -37,22 +39,29 @@ namespace Toolkit
 {
 namespace Internal
 {
+
+class LoadingTask;
+using LoadingTaskPtr = IntrusivePtr<LoadingTask>;
+
 /**
- * The task of loading and packing an image into the atlas.
+ * The task of loading and packing an image into the atlas
  */
-struct LoadingTask
+class LoadingTask : public AsyncTask
 {
+public:
   /**
    * Constructor.
    * @param [in] id of the task
    * @param [in] animatedImageLoading The AnimatedImageLoading to load animated image
    * @param [in] frameIndex The frame index of a frame to be loaded frame
    * @param [in] preMultiplyOnLoad ON if the image's color should be multiplied by it's alpha. Set to OFF if there is no alpha or if the image need to be applied alpha mask.
+   * @param [in] callback The callback that is called when the operation is completed.
    */
   LoadingTask(uint32_t                                 id,
               Dali::AnimatedImageLoading               animatedImageLoading,
               uint32_t                                 frameIndex,
-              DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad);
+              DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad,
+              CallbackBase*                            callback);
 
   /**
    * Constructor.
@@ -64,6 +73,7 @@ struct LoadingTask
    * @param [in] orientationCorrection Reorient the image to respect any orientation metadata in its header.
    * @param [in] preMultiplyOnLoad ON if the image's color should be multiplied by it's alpha. Set to OFF if there is no alpha or if the image need to be applied alpha mask.
    * @param [in] loadPlanes true to load image planes or false to load bitmap image.
+   * @param [in] callback The callback that is called when the operation is completed.
    */
   LoadingTask(uint32_t                                 id,
               const VisualUrl&                         url,
@@ -72,7 +82,8 @@ struct LoadingTask
               SamplingMode::Type                       samplingMode,
               bool                                     orientationCorrection,
               DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad,
-              bool                                     loadPlanes);
+              bool                                     loadPlanes,
+              CallbackBase*                            callback);
 
   /**
    * Constructor.
@@ -83,6 +94,7 @@ struct LoadingTask
    * @param [in] samplingMode The filtering method used when sampling pixels from the input image while fitting it to desired size.
    * @param [in] orientationCorrection Reorient the image to respect any orientation metadata in its header.
    * @param [in] preMultiplyOnLoad ON if the image's color should be multiplied by it's alpha. Set to OFF if there is no alpha or if the image need to be applied alpha mask.
+   * @param [in] callback The callback that is called when the operation is completed.
    */
   LoadingTask(uint32_t                                 id,
               const EncodedImageBuffer&                encodedImageBuffer,
@@ -90,7 +102,8 @@ struct LoadingTask
               FittingMode::Type                        fittingMode,
               SamplingMode::Type                       samplingMode,
               bool                                     orientationCorrection,
-              DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad);
+              DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad,
+              CallbackBase*                            callback);
 
   /**
    * Constructor.
@@ -100,28 +113,37 @@ struct LoadingTask
    * @param [in] contentScale The factor to scale the content
    * @param [in] cropToMask Whether to crop the content to the mask size
    * @param [in] preMultiplyOnLoad ON if the image's color should be multiplied by it's alpha. Set to OFF if there is no alpha.
+   * @param [in] callback The callback that is called when the operation is completed.
    */
   LoadingTask(uint32_t                                 id,
               Devel::PixelBuffer                       pixelBuffer,
               Devel::PixelBuffer                       maskPixelBuffer,
               float                                    contentScale,
               bool                                     cropToMask,
-              DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad);
+              DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad,
+              CallbackBase*                            callback);
 
   /**
-   * Load the image
+   * Destructor.
    */
-  void Load();
+  ~LoadingTask() override;
 
   /**
-   * Apply mask
+   * Process the task accodring to the type
    */
-  void ApplyMask();
+  void Process() override;
 
   /**
-   * Multiply alpha
+   * Whether the task is ready to process.
+   * @return True if the task is ready to process.
    */
-  void MultiplyAlpha();
+  bool IsReady() override;
+
+  /**
+   * @brief Set the Texture Id
+   *
+   */
+  void SetTextureId(TextureManagerType::TextureId id);
 
 private:
   // Undefined
@@ -130,12 +152,28 @@ private:
   // Undefined
   LoadingTask& operator=(const LoadingTask& queue);
 
+  /**
+   * Load the image
+   */
+  void Load();
+
+  /**
+   * Apply mask
+   */
+  void ApplyMask();
+
+  /**
+   * Multiply alpha
+   */
+  void MultiplyAlpha();
+
 public:
   std::vector<Devel::PixelBuffer> pixelBuffers{};              ///< pixelBuffer handle after successful load
                                                                ///< or pixelBuffer to be masked image in the mask task
   VisualUrl                                url;                ///< url of the image to load
   EncodedImageBuffer                       encodedImageBuffer; ///< encoded buffer of the image to load
   uint32_t                                 id;                 ///< The unique id associated with this task.
+  TextureManagerType::TextureId            textureId;          ///< textureId for loading
   ImageDimensions                          dimensions;         ///< dimensions to load
   FittingMode::Type                        fittingMode;        ///< fitting options
   SamplingMode::Type                       samplingMode;       ///< sampling options
@@ -150,89 +188,7 @@ public:
   bool isMaskTask : 1;            ///< whether this task is for mask or not
   bool cropToMask : 1;            ///< Whether to crop the content to the mask size
   bool loadPlanes : 1;            ///< Whether to load image planes
-};
-
-/**
- * The worker thread for image loading.
- */
-class ImageLoadThread : public Thread
-{
-public:
-  /**
-   * Constructor.
-   *
-   * @param[in] mTrigger The trigger to wake up the main thread.
-   */
-  ImageLoadThread(EventThreadCallback* mTrigger);
-
-  /**
-   * Destructor.
-   */
-  ~ImageLoadThread() override;
-
-  /**
-   * Add a task in to the loading queue
-   *
-   * @param[in] task The task added to the queue.
-   *
-   * @note This class takes ownership of the task object
-   */
-  void AddTask(LoadingTask* task);
-
-  /**
-   * Pop the next task out from the completed queue.
-   *
-   * @return The next task to be processed.
-   */
-  LoadingTask* NextCompletedTask();
-
-  /**
-   * Remove the loading task from the waiting queue.
-   */
-  bool CancelTask(uint32_t loadingTaskId);
-
-  /**
-   * Remove all the loading tasks in the waiting queue.
-   */
-  void CancelAll();
-
-private:
-  /**
-   * Pop the next loading task out from the queue to process.
-   *
-   * @return The next task to be processed.
-   */
-  LoadingTask* NextTaskToProcess();
-
-  /**
-   * Add a task in to the loading queue
-   *
-   * @param[in] task The task added to the queue.
-   */
-  void AddCompletedTask(LoadingTask* task);
-
-protected:
-  /**
-   * The entry function of the worker thread.
-   * It fetches loading task from the loadQueue, loads the image and adds to the completeQueue.
-   */
-  void Run() override;
-
-private:
-  // Undefined
-  ImageLoadThread(const ImageLoadThread& thread);
-
-  // Undefined
-  ImageLoadThread& operator=(const ImageLoadThread& thread);
-
-private:
-  Vector<LoadingTask*>             mLoadQueue;     ///<The task queue with images for loading.
-  Vector<LoadingTask*>             mCompleteQueue; ///<The task queue with images loaded.
-  EventThreadCallback*             mTrigger;
-  const Dali::LogFactoryInterface& mLogFactory; ///< The log factory
-
-  ConditionalWait mConditionalWait;
-  Dali::Mutex     mMutex;
+  bool isReady    : 1;            ///< Whether this task ready to run
 };
 
 } // namespace Internal
index 8f0982e..87d3fa6 100644 (file)
@@ -36,7 +36,8 @@ extern Debug::Filter* gTextureManagerLogFilter; ///< Define at texture-manager-i
 #endif
 
 TextureAsyncLoadingHelper::TextureAsyncLoadingHelper(TextureManager& textureManager)
-: TextureAsyncLoadingHelper(Toolkit::AsyncImageLoader::New(), textureManager, AsyncLoadingInfoContainerType())
+: mTextureManager(textureManager),
+  mLoadTaskId(0u)
 {
 }
 
@@ -45,9 +46,9 @@ void TextureAsyncLoadingHelper::LoadAnimatedImage(const TextureManager::TextureI
                                                   const std::uint32_t&                            frameIndex,
                                                   const DevelAsyncImageLoader::PreMultiplyOnLoad& preMultiplyOnLoad)
 {
-  mLoadingInfoContainer.push_back(AsyncLoadingInfo(textureId));
-  auto id                             = GetImplementation(mLoader).LoadAnimatedImage(animatedImageLoading, frameIndex, preMultiplyOnLoad);
-  mLoadingInfoContainer.back().loadId = id;
+  LoadingTaskPtr loadingTask = new LoadingTask(++mLoadTaskId, animatedImageLoading, frameIndex, preMultiplyOnLoad, MakeCallback(this, &TextureAsyncLoadingHelper::AsyncLoadComplete));
+  loadingTask->SetTextureId(textureId);
+  Dali::AsyncTaskManager::Get().AddTask(loadingTask);
 }
 
 void TextureAsyncLoadingHelper::Load(const TextureManager::TextureId&                textureId,
@@ -59,17 +60,18 @@ void TextureAsyncLoadingHelper::Load(const TextureManager::TextureId&
                                      const DevelAsyncImageLoader::PreMultiplyOnLoad& preMultiplyOnLoad,
                                      const bool&                                     loadYuvPlanes)
 {
-  mLoadingInfoContainer.push_back(AsyncLoadingInfo(textureId));
+  LoadingTaskPtr loadingTask;
   if(DALI_UNLIKELY(url.IsBufferResource()))
   {
-    auto id                             = GetImplementation(mLoader).LoadEncodedImageBuffer(mTextureManager.GetEncodedImageBuffer(url.GetUrl()), desiredSize, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad);
-    mLoadingInfoContainer.back().loadId = id;
+    loadingTask = new LoadingTask(++mLoadTaskId, mTextureManager.GetEncodedImageBuffer(url.GetUrl()), desiredSize, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad, MakeCallback(this, &TextureAsyncLoadingHelper::AsyncLoadComplete));
   }
   else
   {
-    auto id                             = GetImplementation(mLoader).Load(url, desiredSize, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad, loadYuvPlanes);
-    mLoadingInfoContainer.back().loadId = id;
+    loadingTask = new LoadingTask(++mLoadTaskId, url, desiredSize, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad, loadYuvPlanes, MakeCallback(this, &TextureAsyncLoadingHelper::AsyncLoadComplete));
   }
+
+  loadingTask->SetTextureId(textureId);
+  Dali::AsyncTaskManager::Get().AddTask(loadingTask);
 }
 
 void TextureAsyncLoadingHelper::ApplyMask(const TextureManager::TextureId&                textureId,
@@ -79,44 +81,18 @@ void TextureAsyncLoadingHelper::ApplyMask(const TextureManager::TextureId&
                                           const bool&                                     cropToMask,
                                           const DevelAsyncImageLoader::PreMultiplyOnLoad& preMultiplyOnLoad)
 {
-  mLoadingInfoContainer.push_back(AsyncLoadingInfo(textureId));
-  auto id                             = GetImplementation(mLoader).ApplyMask(pixelBuffer, maskPixelBuffer, contentScale, cropToMask, preMultiplyOnLoad);
-  mLoadingInfoContainer.back().loadId = id;
-}
-
-TextureAsyncLoadingHelper::TextureAsyncLoadingHelper(TextureAsyncLoadingHelper&& rhs)
-: TextureAsyncLoadingHelper(rhs.mLoader, rhs.mTextureManager, std::move(rhs.mLoadingInfoContainer))
-{
-}
 
-TextureAsyncLoadingHelper::TextureAsyncLoadingHelper(
-  Toolkit::AsyncImageLoader       loader,
-  TextureManager&                 textureManager,
-  AsyncLoadingInfoContainerType&& loadingInfoContainer)
-: mLoader(loader),
-  mTextureManager(textureManager),
-  mLoadingInfoContainer(std::move(loadingInfoContainer))
-{
-  DevelAsyncImageLoader::PixelBufferLoadedSignal(mLoader).Connect(
-    this, &TextureAsyncLoadingHelper::AsyncLoadComplete);
+  LoadingTaskPtr loadingTask = new LoadingTask(++mLoadTaskId, pixelBuffer, maskPixelBuffer, contentScale, cropToMask, preMultiplyOnLoad, MakeCallback(this, &TextureAsyncLoadingHelper::AsyncLoadComplete));
+  loadingTask->SetTextureId(textureId);
+  Dali::AsyncTaskManager::Get().AddTask(loadingTask);
 }
 
-void TextureAsyncLoadingHelper::AsyncLoadComplete(uint32_t                         id,
-                                                  std::vector<Devel::PixelBuffer>& pixelBuffers)
+void TextureAsyncLoadingHelper::AsyncLoadComplete(LoadingTaskPtr task)
 {
-  DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureAsyncLoadingHelper::AsyncLoadComplete( loadId :%d )\n", id);
-  if(mLoadingInfoContainer.size() >= 1u)
+  // Call TextureManager::AsyncLoadComplete
+  if(task->textureId != TextureManager::INVALID_TEXTURE_ID)
   {
-    AsyncLoadingInfo loadingInfo = mLoadingInfoContainer.front();
-
-    // We can assume that First Loading task comes First.
-    if(loadingInfo.loadId == id)
-    {
-      // Call TextureManager::AsyncLoadComplete
-      mTextureManager.AsyncLoadComplete(loadingInfo.textureId, pixelBuffers);
-    }
-
-    mLoadingInfoContainer.pop_front();
+    mTextureManager.AsyncLoadComplete(task->textureId, task->pixelBuffers);
   }
 }
 
index d8830f7..d993737 100644 (file)
@@ -22,7 +22,7 @@
 #include <deque>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/internal/image-loader/async-image-loader-impl.h>
+#include <dali-toolkit/internal/image-loader/loading-task.h>
 #include <dali-toolkit/internal/texture-manager/texture-manager-impl.h>
 
 namespace Dali
@@ -31,27 +31,12 @@ namespace Toolkit
 {
 namespace Internal
 {
+
 /**
  * @brief Helper class to keep the relation between AsyncImageLoader and corresponding LoadingInfo container
  */
 class TextureAsyncLoadingHelper : public ConnectionTracker
 {
-  /**
-   * Struct to hold information about a requested Async load.
-   * This is used to look up a TextureManager::TextureId from the returned AsyncLoad Id.
-   */
-  struct AsyncLoadingInfo
-  {
-    AsyncLoadingInfo(TextureManager::TextureId textureId)
-    : textureId(textureId),
-      loadId(0)
-    {
-    }
-
-    TextureManager::TextureId textureId; ///< The external Texture Id assigned to this load
-    std::uint32_t             loadId;    ///< The load Id used by the async loader to reference this load
-  };
-
 public:
   /**
    * @brief Create an TextureAsyncLoadingHelper.
@@ -113,31 +98,16 @@ public:
   TextureAsyncLoadingHelper(const TextureAsyncLoadingHelper&) = delete;
   TextureAsyncLoadingHelper& operator=(const TextureAsyncLoadingHelper&) = delete;
 
-  TextureAsyncLoadingHelper(TextureAsyncLoadingHelper&& rhs);
-  TextureAsyncLoadingHelper& operator=(TextureAsyncLoadingHelper&& rhs) = delete;
-
-private:                                                              // Private typedefs:
-  typedef std::deque<AsyncLoadingInfo> AsyncLoadingInfoContainerType; ///< The container type used to manage Asynchronous loads in progress
-
 private:
   /**
-   * @brief Main constructor that used by all other constructors
-   */
-  TextureAsyncLoadingHelper(Toolkit::AsyncImageLoader       loader,
-                            TextureManager&                 textureManager,
-                            AsyncLoadingInfoContainerType&& loadingInfoContainer);
-
-  /**
    * @brief Callback to be called when texture loading is complete, it passes the pixel buffer list on to texture manager.
-   * @param[in] id           Loader id
-   * @param[in] pixelBuffers Image data
+   * @param[in] task LoadingTaskPtr
    */
-  void AsyncLoadComplete(std::uint32_t id, std::vector<Devel::PixelBuffer>& pixelBuffers);
+  void AsyncLoadComplete(LoadingTaskPtr task);
 
 private: // Member Variables:
-  Toolkit::AsyncImageLoader     mLoader;
-  TextureManager&               mTextureManager;
-  AsyncLoadingInfoContainerType mLoadingInfoContainer;
+  TextureManager& mTextureManager;
+  uint32_t        mLoadTaskId;
 };
 
 } // namespace Internal
index 643fced..8930d2d 100644 (file)
@@ -34,8 +34,6 @@
 namespace
 {
 constexpr auto INITIAL_HASH_NUMBER                     = size_t{0u};
-constexpr auto DEFAULT_NUMBER_OF_LOCAL_LOADER_THREADS  = size_t{4u};
-constexpr auto DEFAULT_NUMBER_OF_REMOTE_LOADER_THREADS = size_t{8u};
 
 constexpr auto TEXTURE_INDEX      = 0u; ///< The Index for texture
 constexpr auto MASK_TEXTURE_INDEX = 1u; ///< The Index for mask texture
@@ -44,26 +42,6 @@ constexpr auto NUMBER_OF_LOCAL_LOADER_THREADS_ENV  = "DALI_TEXTURE_LOCAL_THREADS
 constexpr auto NUMBER_OF_REMOTE_LOADER_THREADS_ENV = "DALI_TEXTURE_REMOTE_THREADS";
 constexpr auto LOAD_IMAGE_YUV_PLANES_ENV           = "DALI_LOAD_IMAGE_YUV_PLANES";
 
-size_t GetNumberOfThreads(const char* environmentVariable, size_t defaultValue)
-{
-  using Dali::EnvironmentVariable::GetEnvironmentVariable;
-  auto           numberString          = GetEnvironmentVariable(environmentVariable);
-  auto           numberOfThreads       = numberString ? std::strtoul(numberString, nullptr, 10) : 0;
-  constexpr auto MAX_NUMBER_OF_THREADS = 100u;
-  DALI_ASSERT_DEBUG(numberOfThreads < MAX_NUMBER_OF_THREADS);
-  return (numberOfThreads > 0 && numberOfThreads < MAX_NUMBER_OF_THREADS) ? numberOfThreads : defaultValue;
-}
-
-size_t GetNumberOfLocalLoaderThreads()
-{
-  return GetNumberOfThreads(NUMBER_OF_LOCAL_LOADER_THREADS_ENV, DEFAULT_NUMBER_OF_LOCAL_LOADER_THREADS);
-}
-
-size_t GetNumberOfRemoteLoaderThreads()
-{
-  return GetNumberOfThreads(NUMBER_OF_REMOTE_LOADER_THREADS_ENV, DEFAULT_NUMBER_OF_REMOTE_LOADER_THREADS);
-}
-
 bool NeedToLoadYuvPlanes()
 {
   auto loadYuvPlanesString = Dali::EnvironmentVariable::GetEnvironmentVariable(LOAD_IMAGE_YUV_PLANES_ENV);
@@ -132,8 +110,7 @@ TextureManager::MaskingData::MaskingData()
 
 TextureManager::TextureManager()
 : mTextureCacheManager(),
-  mAsyncLocalLoaders(GetNumberOfLocalLoaderThreads(), [&]() { return TextureAsyncLoadingHelper(*this); }),
-  mAsyncRemoteLoaders(GetNumberOfRemoteLoaderThreads(), [&]() { return TextureAsyncLoadingHelper(*this); }),
+  mAsyncLoader(std::unique_ptr<TextureAsyncLoadingHelper>(new TextureAsyncLoadingHelper(*this))),
   mLifecycleObservers(),
   mLoadQueue(),
   mRemoveQueue(),
@@ -551,7 +528,6 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
 
     // Update preMultiplyOnLoad value. It should be changed according to preMultiplied value of the cached info.
     preMultiplyOnLoad = mTextureCacheManager[cacheIndex].preMultiplied ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
-
     DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureManager::RequestLoad( url=%s observer=%p ) Using cached texture id@%d, textureId=%d, maskTextureId=%d, frameindex=%d, premultiplied=%d\n", url.GetUrl().c_str(), observer, cacheIndex.GetIndex(), textureId, maskTextureId, frameIndex, mTextureCacheManager[cacheIndex].preMultiplied ? 1 : 0);
   }
 
@@ -563,7 +539,6 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
 
     // Cache new texutre, and get cacheIndex.
     cacheIndex = mTextureCacheManager.AppendCache(TextureInfo(textureId, maskTextureId, url, desiredSize, contentScale, fittingMode, samplingMode, false, cropToMask, useAtlas, textureHash, orientationCorrection, preMultiply, animatedImageLoading, frameIndex, loadYuvPlanes));
-
     DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureManager::RequestLoad( url=%s observer=%p ) New texture, cacheIndex:%d, textureId=%d, maskTextureId=%d, frameindex=%d premultiply=%d\n", url.GetUrl().c_str(), observer, cacheIndex.GetIndex(), textureId, maskTextureId, frameIndex, preMultiply);
   }
 
@@ -587,7 +562,6 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
      TextureManager::LoadState::MASK_CANCELLED != textureInfo.loadState)
   {
     DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Verbose, "TextureManager::RequestLoad( url=%s observer=%p ) ForcedReload cacheIndex:%d, textureId=%d, maskTextureId=%d\n", url.GetUrl().c_str(), observer, cacheIndex.GetIndex(), textureId, maskTextureId);
-
     textureInfo.loadState = TextureManager::LoadState::NOT_STARTED;
   }
 
@@ -898,21 +872,17 @@ void TextureManager::QueueLoadTexture(const TextureManager::TextureInfo& texture
 void TextureManager::LoadTexture(TextureManager::TextureInfo& textureInfo, TextureUploadObserver* observer)
 {
   DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::LoadTexture(): url:%s sync:%s\n", textureInfo.url.GetUrl().c_str(), textureInfo.loadSynchronously ? "T" : "F");
-
   textureInfo.loadState = LoadState::LOADING;
   if(!textureInfo.loadSynchronously)
   {
-    auto& loadersContainer  = (textureInfo.url.IsLocalResource() || textureInfo.url.IsBufferResource()) ? mAsyncLocalLoaders : mAsyncRemoteLoaders;
-    auto  loadingHelperIt   = loadersContainer.GetNext();
     auto  premultiplyOnLoad = (textureInfo.preMultiplyOnLoad && textureInfo.maskTextureId == INVALID_TEXTURE_ID) ? DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF;
-    DALI_ASSERT_ALWAYS(loadingHelperIt != loadersContainer.End());
     if(textureInfo.animatedImageLoading)
     {
-      loadingHelperIt->LoadAnimatedImage(textureInfo.textureId, textureInfo.animatedImageLoading, textureInfo.frameIndex, premultiplyOnLoad);
+      mAsyncLoader->LoadAnimatedImage(textureInfo.textureId, textureInfo.animatedImageLoading, textureInfo.frameIndex, premultiplyOnLoad);
     }
     else
     {
-      loadingHelperIt->Load(textureInfo.textureId, textureInfo.url, textureInfo.desiredSize, textureInfo.fittingMode, textureInfo.samplingMode, textureInfo.orientationCorrection, premultiplyOnLoad, textureInfo.loadYuvPlanes);
+      mAsyncLoader->Load(textureInfo.textureId, textureInfo.url, textureInfo.desiredSize, textureInfo.fittingMode, textureInfo.samplingMode, textureInfo.orientationCorrection, premultiplyOnLoad, textureInfo.loadYuvPlanes);
     }
   }
   ObserveTexture(textureInfo, observer);
@@ -986,7 +956,6 @@ void TextureManager::AsyncLoadComplete(const TextureManager::TextureId& textureI
     TextureInfo& textureInfo(mTextureCacheManager[cacheIndex]);
 
     DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "  textureId:%d Url:%s CacheIndex:%d LoadState: %s\n", textureInfo.textureId, textureInfo.url.GetUrl().c_str(), cacheIndex.GetIndex(), GET_LOAD_STATE_STRING(textureInfo.loadState));
-
     if(textureInfo.loadState != LoadState::CANCELLED && textureInfo.loadState != LoadState::MASK_CANCELLED)
     {
       // textureInfo can be invalidated after this call (as the mTextureInfoContainer may be modified)
@@ -1226,11 +1195,8 @@ void TextureManager::ApplyMask(TextureManager::TextureInfo& textureInfo, const T
     DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::ApplyMask(): url:%s sync:%s\n", textureInfo.url.GetUrl().c_str(), textureInfo.loadSynchronously ? "T" : "F");
 
     textureInfo.loadState   = LoadState::MASK_APPLYING;
-    auto& loadersContainer  = (textureInfo.url.IsLocalResource() || textureInfo.url.IsBufferResource()) ? mAsyncLocalLoaders : mAsyncRemoteLoaders;
-    auto  loadingHelperIt   = loadersContainer.GetNext();
-    auto  premultiplyOnLoad = textureInfo.preMultiplyOnLoad ? DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF;
-    DALI_ASSERT_ALWAYS(loadingHelperIt != loadersContainer.End());
-    loadingHelperIt->ApplyMask(textureInfo.textureId, pixelBuffer, maskPixelBuffer, textureInfo.scaleFactor, textureInfo.cropToMask, premultiplyOnLoad);
+    auto premultiplyOnLoad = textureInfo.preMultiplyOnLoad ? DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF;
+    mAsyncLoader->ApplyMask(textureInfo.textureId, pixelBuffer, maskPixelBuffer, textureInfo.scaleFactor, textureInfo.cropToMask, premultiplyOnLoad);
   }
 }
 
@@ -1305,7 +1271,6 @@ void TextureManager::NotifyObservers(TextureManager::TextureInfo& textureInfo, c
     // Texture load requests for the same URL are deferred until the end of this
     // method.
     DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::NotifyObservers() textureId:%d url:%s loadState:%s\n", textureId, info->url.GetUrl().c_str(), GET_LOAD_STATE_STRING(info->loadState));
-
     // It is possible for the observer to be deleted.
     // Disconnect and remove the observer first.
     observer->DestructionSignal().Disconnect(this, &TextureManager::ObserverDestroyed);
index 6b3f1a7..791553c 100644 (file)
 #include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
 #include <dali/public-api/common/dali-vector.h>
 #include <dali/public-api/rendering/geometry.h>
+#include <dali/public-api/adaptor-framework/round-robin-container-view.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/image-loader/image-atlas.h>
-#include <dali-toolkit/internal/helpers/round-robin-container-view.h>
 #include <dali-toolkit/internal/texture-manager/texture-cache-manager.h>
 #include <dali-toolkit/internal/texture-manager/texture-manager-type.h>
 #include <dali-toolkit/internal/texture-manager/texture-upload-observer.h>
@@ -650,10 +650,7 @@ private:
 
 private:                                    // Member Variables:
   TextureCacheManager mTextureCacheManager; ///< Manager the life-cycle and caching of Textures
-
-  RoundRobinContainerView<TextureAsyncLoadingHelper> mAsyncLocalLoaders;  ///< The Asynchronous image loaders used to provide all local async loads
-  RoundRobinContainerView<TextureAsyncLoadingHelper> mAsyncRemoteLoaders; ///< The Asynchronous image loaders used to provide all remote async loads
-
+  std::unique_ptr<TextureAsyncLoadingHelper> mAsyncLoader;  ///< The Asynchronous image loader used to provide all local async loads
   Dali::Vector<LifecycleObserver*>        mLifecycleObservers;      ///< Lifecycle observers of texture manager
   Dali::Vector<QueueElement>              mLoadQueue;               ///< Queue of textures to load after NotifyObservers
   Dali::Vector<QueueElement>              mRemoveQueue;             ///< Queue of textures to remove after NotifyObservers
index b752105..0d2dfb0 100644 (file)
 #include <dali/devel-api/threading/thread.h>
 #include <dali/integration-api/adaptor-framework/log-factory-interface.h>
 #include <dali/public-api/signals/connection-tracker.h>
+#include <dali/public-api/adaptor-framework/round-robin-container-view.h>
 #include <memory>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/internal/helpers/round-robin-container-view.h>
 #include <dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h>
 #include <dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.h>
 
diff --git a/dali-toolkit/internal/visuals/svg/svg-rasterize-thread.cpp b/dali-toolkit/internal/visuals/svg/svg-rasterize-thread.cpp
deleted file mode 100644 (file)
index c1ebd67..0000000
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * 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.
- * 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.
- *
- */
-
-// CLASS HEADER
-#include "svg-rasterize-thread.h"
-
-// EXTERNAL INCLUDES
-#include <dali/devel-api/adaptor-framework/environment-variable.h>
-#include <dali/devel-api/adaptor-framework/file-loader.h>
-#include <dali/devel-api/adaptor-framework/thread-settings.h>
-#include <dali/integration-api/adaptor-framework/adaptor.h>
-#include <dali/integration-api/debug.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/visuals/svg/svg-visual.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Internal
-{
-namespace
-{
-constexpr auto DEFAULT_NUMBER_OF_SVG_RASTERIZE_THREADS = size_t{4u};
-constexpr auto NUMBER_OF_SVG_RASTERIZE_THREADS_ENV     = "DALI_SVG_RASTERIZE_THREADS";
-
-size_t GetNumberOfThreads(const char* environmentVariable, size_t defaultValue)
-{
-  auto           numberString          = EnvironmentVariable::GetEnvironmentVariable(environmentVariable);
-  auto           numberOfThreads       = numberString ? std::strtoul(numberString, nullptr, 10) : 0;
-  constexpr auto MAX_NUMBER_OF_THREADS = 10u;
-  DALI_ASSERT_DEBUG(numberOfThreads < MAX_NUMBER_OF_THREADS);
-  return (numberOfThreads > 0 && numberOfThreads < MAX_NUMBER_OF_THREADS) ? numberOfThreads : defaultValue;
-}
-
-#if defined(DEBUG_ENABLED)
-Debug::Filter* gVectorImageLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_VECTOR_IMAGE");
-#endif
-
-} // unnamed namespace
-
-SvgTask::SvgTask(SvgVisual* svgVisual, VectorImageRenderer vectorRenderer)
-: mSvgVisual(svgVisual),
-  mVectorRenderer(vectorRenderer),
-  mHasSucceeded(false)
-{
-}
-
-SvgVisual* SvgTask::GetSvgVisual() const
-{
-  return mSvgVisual.Get();
-}
-
-PixelData SvgTask::GetPixelData() const
-{
-  return PixelData();
-}
-
-bool SvgTask::HasSucceeded() const
-{
-  return mHasSucceeded;
-}
-
-SvgLoadingTask::SvgLoadingTask(SvgVisual* svgVisual, VectorImageRenderer vectorRenderer, const VisualUrl& url, float dpi)
-: SvgTask(svgVisual, vectorRenderer),
-  mUrl(url),
-  mDpi(dpi)
-{
-}
-
-SvgLoadingTask::~SvgLoadingTask()
-{
-}
-
-void SvgLoadingTask::Process()
-{
-  if(mVectorRenderer.IsLoaded())
-  {
-    // Already loaded
-    mHasSucceeded = true;
-    return;
-  }
-
-  Dali::Vector<uint8_t> buffer;
-
-  if(!mUrl.IsLocalResource())
-  {
-    if(!Dali::FileLoader::DownloadFileSynchronously(mUrl.GetUrl(), buffer))
-    {
-      DALI_LOG_ERROR("Failed to download file! [%s]\n", mUrl.GetUrl().c_str());
-      return;
-    }
-  }
-  else
-  {
-    if(!Dali::FileLoader::ReadFile(mUrl.GetUrl(), buffer))
-    {
-      DALI_LOG_ERROR("Failed to read file! [%s]\n", mUrl.GetUrl().c_str());
-      return;
-    }
-  }
-
-  buffer.PushBack('\0');
-
-  if(!mVectorRenderer.Load(buffer, mDpi))
-  {
-    DALI_LOG_ERROR("Failed to load data! [%s]\n", mUrl.GetUrl().c_str());
-    return;
-  }
-
-  mHasSucceeded = true;
-}
-
-SvgRasterizingTask::SvgRasterizingTask(SvgVisual* svgVisual, VectorImageRenderer vectorRenderer, unsigned int width, unsigned int height)
-: SvgTask(svgVisual, vectorRenderer),
-  mWidth(width),
-  mHeight(height)
-{
-}
-
-SvgRasterizingTask::~SvgRasterizingTask()
-{
-}
-
-void SvgRasterizingTask::Process()
-{
-  if(!mVectorRenderer.IsLoaded())
-  {
-    DALI_LOG_ERROR("File is not loaded!\n");
-    return;
-  }
-
-  DALI_LOG_INFO(gVectorImageLogFilter, Debug::Verbose, "Rasterize: (%d x %d) [%p]\n", mWidth, mHeight, this);
-
-  Devel::PixelBuffer pixelBuffer = mVectorRenderer.Rasterize(mWidth, mHeight);
-  if(!pixelBuffer)
-  {
-    DALI_LOG_ERROR("Rasterize is failed!\n");
-    return;
-  }
-
-  mPixelData    = Devel::PixelBuffer::Convert(pixelBuffer);
-  mHasSucceeded = true;
-}
-
-bool SvgRasterizingTask::IsReady()
-{
-  return mVectorRenderer.IsLoaded();
-}
-
-PixelData SvgRasterizingTask::GetPixelData() const
-{
-  return mPixelData;
-}
-
-SvgRasterizeThread::SvgRasterizeThread(SvgRasterizeManager& svgRasterizeManager)
-: mConditionalWait(),
-  mLogFactory(Dali::Adaptor::Get().GetLogFactory()),
-  mSvgRasterizeManager(svgRasterizeManager),
-  mDestroyThread(false),
-  mIsThreadStarted(false),
-  mIsThreadIdle(true)
-{
-}
-
-SvgRasterizeThread::~SvgRasterizeThread()
-{
-  // Stop the thread
-  {
-    ConditionalWait::ScopedLock lock(mConditionalWait);
-    mDestroyThread = true;
-    mConditionalWait.Notify(lock);
-  }
-
-  Join();
-}
-
-bool SvgRasterizeThread::RequestRasterize()
-{
-  if(!mIsThreadStarted)
-  {
-    Start();
-    mIsThreadStarted = true;
-  }
-
-  {
-    // Lock while adding task to the queue
-    ConditionalWait::ScopedLock lock(mConditionalWait);
-
-    if(mIsThreadIdle)
-    {
-      mIsThreadIdle = false;
-
-      // wake up the thread
-      mConditionalWait.Notify(lock);
-      return true;
-    }
-  }
-
-  return false;
-}
-
-void SvgRasterizeThread::Run()
-{
-  SetThreadName("SvgRasterizeThread");
-  mLogFactory.InstallLogFunction();
-
-  while(!mDestroyThread)
-  {
-    SvgTaskPtr task = mSvgRasterizeManager.NextTaskToProcess();
-    if(!task)
-    {
-      ConditionalWait::ScopedLock lock(mConditionalWait);
-      mIsThreadIdle = true;
-      mConditionalWait.Wait(lock);
-    }
-    else
-    {
-      task->Process();
-
-      mSvgRasterizeManager.AddCompletedTask(task);
-    }
-  }
-}
-
-SvgRasterizeManager::SvgRasterizeManager()
-: mRasterizers(GetNumberOfThreads(NUMBER_OF_SVG_RASTERIZE_THREADS_ENV, DEFAULT_NUMBER_OF_SVG_RASTERIZE_THREADS), [&]() { return RasterizeHelper(*this); }),
-  mTrigger(new EventThreadCallback(MakeCallback(this, &SvgRasterizeManager::ApplyRasterizedSVGToSampler))),
-  mProcessorRegistered(false)
-{
-}
-
-SvgRasterizeManager::~SvgRasterizeManager()
-{
-  if(mProcessorRegistered)
-  {
-    Adaptor::Get().UnregisterProcessor(*this);
-  }
-
-  mRasterizers.Clear();
-}
-
-void SvgRasterizeManager::AddTask(SvgTaskPtr task)
-{
-  {
-    // Lock while adding task to the queue
-    Mutex::ScopedLock lock(mMutex);
-
-    // There are other tasks waiting for the rasterization
-    if(!mRasterizeTasks.empty())
-    {
-      // Remove the tasks with the same renderer.
-      // Older task which waiting to rasterize and apply the svg to the same renderer is expired.
-      // Rasterizing task only, loading task is not duplicated.
-      for(std::vector<SvgTaskPtr>::iterator it = mRasterizeTasks.begin(), endIt = mRasterizeTasks.end(); it != endIt; ++it)
-      {
-        if((*it) && (*it)->GetSvgVisual() == task->GetSvgVisual())
-        {
-          SvgRasterizingTask* oldTask = dynamic_cast<SvgRasterizingTask*>(it->Get());
-          SvgRasterizingTask* newTask = dynamic_cast<SvgRasterizingTask*>(task.Get());
-          if(oldTask && newTask)
-          {
-            mRasterizeTasks.erase(it);
-            break;
-          }
-        }
-      }
-    }
-
-    mRasterizeTasks.push_back(task);
-  }
-
-  size_t count = mRasterizers.GetElementCount();
-  size_t index = 0;
-  while(index++ < count)
-  {
-    auto rasterizerHelperIt = mRasterizers.GetNext();
-    DALI_ASSERT_ALWAYS(rasterizerHelperIt != mRasterizers.End());
-
-    if(rasterizerHelperIt->RequestRasterize())
-    {
-      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(!mProcessorRegistered)
-  {
-    Adaptor::Get().RegisterProcessor(*this);
-    mProcessorRegistered = true;
-  }
-
-  return;
-}
-
-SvgTaskPtr SvgRasterizeManager::NextCompletedTask()
-{
-  // Lock while popping task out from the queue
-  Mutex::ScopedLock lock(mMutex);
-
-  if(mCompletedTasks.empty())
-  {
-    return SvgTaskPtr();
-  }
-
-  std::vector<SvgTaskPtr>::iterator next     = mCompletedTasks.begin();
-  SvgTaskPtr                        nextTask = *next;
-  mCompletedTasks.erase(next);
-
-  return nextTask;
-}
-
-void SvgRasterizeManager::RemoveTask(SvgVisual* visual)
-{
-  {
-    // Lock while remove task from the queue
-    Mutex::ScopedLock lock(mMutex);
-    if(!mRasterizeTasks.empty())
-    {
-      for(std::vector<SvgTaskPtr>::iterator it = mRasterizeTasks.begin(); it != mRasterizeTasks.end();)
-      {
-        if((*it) && (*it)->GetSvgVisual() == visual)
-        {
-          it = mRasterizeTasks.erase(it);
-        }
-        else
-        {
-          it++;
-        }
-      }
-    }
-  }
-
-  UnregisterProcessor();
-}
-
-SvgTaskPtr SvgRasterizeManager::NextTaskToProcess()
-{
-  // Lock while popping task out from the queue
-  Mutex::ScopedLock lock(mMutex);
-
-  // pop out the next task from the queue
-  SvgTaskPtr nextTask = nullptr;
-
-  for(auto iter = mRasterizeTasks.begin(), endIter = mRasterizeTasks.end(); iter != endIter; ++iter)
-  {
-    if((*iter)->IsReady())
-    {
-      nextTask = *iter;
-      mRasterizeTasks.erase(iter);
-      break;
-    }
-  }
-
-  return nextTask;
-}
-
-void SvgRasterizeManager::AddCompletedTask(SvgTaskPtr task)
-{
-  // Lock while adding task to the queue
-  Mutex::ScopedLock lock(mMutex);
-  mCompletedTasks.push_back(task);
-
-  // wake up the main thread
-  mTrigger->Trigger();
-}
-
-void SvgRasterizeManager::ApplyRasterizedSVGToSampler()
-{
-  while(SvgTaskPtr task = NextCompletedTask())
-  {
-    DALI_LOG_INFO(gVectorImageLogFilter, Debug::Verbose, "task = %p\n", task.Get());
-
-    task->GetSvgVisual()->ApplyRasterizedImage(task->GetPixelData(), task->HasSucceeded());
-  }
-
-  UnregisterProcessor();
-}
-
-void SvgRasterizeManager::Process(bool postProcessor)
-{
-  ApplyRasterizedSVGToSampler();
-}
-
-void SvgRasterizeManager::UnregisterProcessor()
-{
-  Mutex::ScopedLock lock(mMutex);
-
-  if(mProcessorRegistered)
-  {
-    if(mRasterizeTasks.empty() && mCompletedTasks.empty())
-    {
-      Adaptor::Get().UnregisterProcessor(*this);
-      mProcessorRegistered = false;
-    }
-  }
-}
-
-SvgRasterizeManager::RasterizeHelper::RasterizeHelper(SvgRasterizeManager& svgRasterizeManager)
-: RasterizeHelper(std::unique_ptr<SvgRasterizeThread>(new SvgRasterizeThread(svgRasterizeManager)), svgRasterizeManager)
-{
-}
-
-SvgRasterizeManager::RasterizeHelper::RasterizeHelper(RasterizeHelper&& rhs)
-: RasterizeHelper(std::move(rhs.mRasterizer), rhs.mSvgRasterizeManager)
-{
-}
-
-SvgRasterizeManager::RasterizeHelper::RasterizeHelper(std::unique_ptr<SvgRasterizeThread> rasterizer, SvgRasterizeManager& svgRasterizeManager)
-: mRasterizer(std::move(rasterizer)),
-  mSvgRasterizeManager(svgRasterizeManager)
-{
-}
-
-bool SvgRasterizeManager::RasterizeHelper::RequestRasterize()
-{
-  return mRasterizer->RequestRasterize();
-}
-} // namespace Internal
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h b/dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h
deleted file mode 100644 (file)
index c9c305b..0000000
+++ /dev/null
@@ -1,378 +0,0 @@
-#ifndef DALI_TOOLKIT_SVG_RASTERIZE_THREAD_H
-#define DALI_TOOLKIT_SVG_RASTERIZE_THREAD_H
-
-/*
- * 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.
- * 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 <dali/devel-api/adaptor-framework/event-thread-callback.h>
-#include <dali/devel-api/adaptor-framework/vector-image-renderer.h>
-#include <dali/devel-api/threading/conditional-wait.h>
-#include <dali/devel-api/threading/mutex.h>
-#include <dali/devel-api/threading/thread.h>
-#include <dali/integration-api/adaptor-framework/log-factory-interface.h>
-#include <dali/integration-api/processor-interface.h>
-#include <dali/public-api/common/intrusive-ptr.h>
-#include <dali/public-api/common/vector-wrapper.h>
-#include <dali/public-api/images/pixel-data.h>
-#include <dali/public-api/object/ref-object.h>
-#include <memory>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/helpers/round-robin-container-view.h>
-#include <dali-toolkit/internal/visuals/visual-url.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Internal
-{
-class SvgVisual;
-typedef IntrusivePtr<SvgVisual> SvgVisualPtr;
-class SvgTask;
-typedef IntrusivePtr<SvgTask> SvgTaskPtr;
-class SvgRasterizeManager;
-
-/**
- * The svg rasterizing tasks to be processed in the worker thread.
- *
- * Life cycle of a rasterizing task is as follows:
- * 1. Created by SvgVisual in the main thread
- * 2. Queued in the worked thread waiting to be processed.
- * 3. If this task gets its turn to do the rasterization, it triggers main thread to apply the rasterized image to material then been deleted in main thread call back
- *    Or if this task is been removed ( new image/size set to the visual or actor off stage) before its turn to be processed, it then been deleted in the worker thread.
- */
-class SvgTask : public RefObject
-{
-public:
-  /**
-   * Constructor
-   * @param[in] svgVisual The visual which the rasterized image to be applied.
-   * @param[in] vectorRenderer The vector rasterizer.
-   */
-  SvgTask(SvgVisual* svgVisual, VectorImageRenderer vectorRenderer);
-
-  /**
-   * Destructor.
-   */
-  virtual ~SvgTask() = default;
-
-  /**
-   * Process the task
-   */
-  virtual void Process() = 0;
-
-  /**
-   * Whether the task is ready to process.
-   * @return True if the task is ready to process.
-   */
-  virtual bool IsReady()
-  {
-    return true;
-  }
-
-  /**
-   * Whether the task has succeeded.
-   * @return True if the task has succeeded.
-   */
-  bool HasSucceeded() const;
-
-  /**
-   * Get the svg visual
-   */
-  SvgVisual* GetSvgVisual() const;
-
-  /**
-   * Get the rasterization result.
-   * @return The pixel data with the rasterized pixels.
-   */
-  virtual PixelData GetPixelData() const;
-
-private:
-  // Undefined
-  SvgTask(const SvgTask& task) = delete;
-
-  // Undefined
-  SvgTask& operator=(const SvgTask& task) = delete;
-
-protected:
-  SvgVisualPtr        mSvgVisual;
-  VectorImageRenderer mVectorRenderer;
-  bool                mHasSucceeded;
-};
-
-class SvgLoadingTask : public SvgTask
-{
-public:
-  /**
-   * Constructor
-   * @param[in] svgVisual The visual which the rasterized image to be applied.
-   * @param[in] vectorRenderer The vector rasterizer.
-   * @param[in] url The URL to svg resource to use.
-   * @param[in] dpi The DPI of the screen.
-   */
-  SvgLoadingTask(SvgVisual* svgVisual, VectorImageRenderer vectorRenderer, const VisualUrl& url, float dpi);
-
-  /**
-   * Destructor.
-   */
-  ~SvgLoadingTask() override;
-
-  /**
-   * Process the task
-   */
-  void Process() override;
-
-private:
-  // Undefined
-  SvgLoadingTask(const SvgLoadingTask& task) = delete;
-
-  // Undefined
-  SvgLoadingTask& operator=(const SvgLoadingTask& task) = delete;
-
-private:
-  VisualUrl mUrl;
-  float     mDpi;
-};
-
-class SvgRasterizingTask : public SvgTask
-{
-public:
-  /**
-   * Constructor
-   * @param[in] svgVisual The visual which the rasterized image to be applied.
-   * @param[in] vectorRenderer The vector rasterizer.
-   * @param[in] width The rasterization width.
-   * @param[in] height The rasterization height.
-   */
-  SvgRasterizingTask(SvgVisual* svgVisual, VectorImageRenderer vectorRenderer, unsigned int width, unsigned int height);
-
-  /**
-   * Destructor.
-   */
-  ~SvgRasterizingTask() override;
-
-  /**
-   * Process the task accodring to the type
-   */
-  void Process() override;
-
-  /**
-   * Whether the task is ready to process.
-   * @return True if the task is ready to process.
-   */
-  bool IsReady() override;
-
-  /**
-   * Get the rasterization result.
-   * @return The pixel data with the rasterized pixels.
-   */
-  PixelData GetPixelData() const override;
-
-private:
-  // Undefined
-  SvgRasterizingTask(const SvgRasterizingTask& task) = delete;
-
-  // Undefined
-  SvgRasterizingTask& operator=(const SvgRasterizingTask& task) = delete;
-
-private:
-  PixelData mPixelData;
-  uint32_t  mWidth;
-  uint32_t  mHeight;
-};
-
-/**
- * The worker thread for SVG rasterization.
- */
-class SvgRasterizeThread : public Thread
-{
-public:
-  /**
-   * Constructor.
-   */
-  SvgRasterizeThread(SvgRasterizeManager& svgRasterizeManager);
-
-  /**
-   * Destructor.
-   */
-  ~SvgRasterizeThread() override;
-
-  /**
-   * @brief Request the thread to rasterizes the task.
-   * @return True if the request succeeds, otherwise false.
-   */
-  bool RequestRasterize();
-
-protected:
-  /**
-   * The entry function of the worker thread.
-   * It rasterizes the image.
-   */
-  void Run() override;
-
-private:
-  // Undefined
-  SvgRasterizeThread(const SvgRasterizeThread& thread) = delete;
-
-  // Undefined
-  SvgRasterizeThread& operator=(const SvgRasterizeThread& thread) = delete;
-
-private:
-  ConditionalWait                  mConditionalWait;
-  const Dali::LogFactoryInterface& mLogFactory;
-  SvgRasterizeManager&             mSvgRasterizeManager;
-  bool                             mDestroyThread;
-  bool                             mIsThreadStarted;
-  bool                             mIsThreadIdle;
-};
-
-/**
- * The manager for SVG rasterization.
- */
-class SvgRasterizeManager : Integration::Processor
-{
-public:
-  /**
-   * Constructor.
-   *
-   * @param[in] trigger The trigger to wake up the main thread.
-   */
-  SvgRasterizeManager();
-
-  /**
-   * Destructor.
-   */
-  ~SvgRasterizeManager() override;
-
-  /**
-   * Add a rasterization task into the waiting queue, called by main thread.
-   *
-   * @param[in] task The task added to the queue.
-   */
-  void AddTask(SvgTaskPtr task);
-
-  /**
-   * Pop the next task out from the completed queue, called by main thread.
-   *
-   * @return The next task in the completed queue.
-   */
-  SvgTaskPtr NextCompletedTask();
-
-  /**
-   * Remove the task with the given visual from the waiting queue, called by main thread.
-   *
-   * Typically called when the actor is put off stage, so the renderer is not needed anymore.
-   *
-   * @param[in] visual The visual pointer.
-   */
-  void RemoveTask(SvgVisual* visual);
-
-  /**
-   * @copydoc Dali::Integration::Processor::Process()
-   */
-  void Process(bool postProcessor) override;
-
-  /**
-   * Pop the next task out from the queue.
-   *
-   * @return The next task to be processed.
-   */
-  SvgTaskPtr NextTaskToProcess();
-
-  /**
-   * Add a task in to the queue
-   *
-   * @param[in] task The task added to the queue.
-   */
-  void AddCompletedTask(SvgTaskPtr task);
-
-private:
-  /**
-   * Applies the rasterized image to material
-   */
-  void ApplyRasterizedSVGToSampler();
-
-  /**
-   * @brief Unregister a previously registered processor
-   *
-   */
-  void UnregisterProcessor();
-
-private:
-  /**
-   * @brief Helper class to keep the relation between SvgRasterizeThread and corresponding container
-   */
-  class RasterizeHelper
-  {
-  public:
-    /**
-     * @brief Create an RasterizeHelper.
-     *
-     * @param[in] svgRasterizeManager Reference to the SvgRasterizeManager
-     */
-    RasterizeHelper(SvgRasterizeManager& svgRasterizeManager);
-
-    /**
-     * @brief Request the thread to rasterizes the task.
-     * @return True if the request succeeds, otherwise false.
-     */
-    bool RequestRasterize();
-
-  public:
-    RasterizeHelper(const RasterizeHelper&) = delete;
-    RasterizeHelper& operator=(const RasterizeHelper&) = delete;
-
-    RasterizeHelper(RasterizeHelper&& rhs);
-    RasterizeHelper& operator=(RasterizeHelper&& rhs) = delete;
-
-  private:
-    /**
-     * @brief Main constructor that used by all other constructors
-     */
-    RasterizeHelper(std::unique_ptr<SvgRasterizeThread> rasterizer, SvgRasterizeManager& svgRasterizeManager);
-
-  private:
-    std::unique_ptr<SvgRasterizeThread> mRasterizer;
-    SvgRasterizeManager&                mSvgRasterizeManager;
-  };
-
-private:
-  // Undefined
-  SvgRasterizeManager(const SvgRasterizeManager& thread);
-
-  // Undefined
-  SvgRasterizeManager& operator=(const SvgRasterizeManager& thread);
-
-private:
-  std::vector<SvgTaskPtr> mRasterizeTasks; //The queue of the tasks waiting to rasterize the SVG image
-  std::vector<SvgTaskPtr> mCompletedTasks; //The queue of the tasks with the SVG rasterization completed
-
-  RoundRobinContainerView<RasterizeHelper> mRasterizers;
-
-  Dali::Mutex                          mMutex;
-  std::unique_ptr<EventThreadCallback> mTrigger;
-  bool                                 mProcessorRegistered;
-};
-
-} // namespace Internal
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_SVG_RASTERIZE_THREAD_H
diff --git a/dali-toolkit/internal/visuals/svg/svg-task.cpp b/dali-toolkit/internal/visuals/svg/svg-task.cpp
new file mode 100644 (file)
index 0000000..67cff0f
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * 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.
+ * 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.
+ *
+ */
+
+// CLASS HEADER
+#include "svg-task.h"
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/file-loader.h>
+#include <dali/integration-api/adaptor-framework/adaptor.h>
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/visuals/svg/svg-visual.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+SvgTask::SvgTask(VectorImageRenderer vectorRenderer, CallbackBase* callback)
+: AsyncTask(callback),
+  mVectorRenderer(vectorRenderer),
+  mHasSucceeded(false)
+{
+}
+
+PixelData SvgTask::GetPixelData() const
+{
+  return PixelData();
+}
+
+bool SvgTask::HasSucceeded() const
+{
+  return mHasSucceeded;
+}
+
+VectorImageRenderer SvgTask::GetRenderer()
+{
+  return mVectorRenderer;
+}
+
+SvgLoadingTask::SvgLoadingTask(VectorImageRenderer vectorRenderer, const VisualUrl& url, float dpi, CallbackBase* callback)
+: SvgTask(vectorRenderer, callback),
+  mUrl(url),
+  mDpi(dpi)
+{
+}
+
+SvgLoadingTask::~SvgLoadingTask()
+{
+}
+
+void SvgLoadingTask::Process()
+{
+  if(mVectorRenderer.IsLoaded())
+  {
+    // Already loaded
+    mHasSucceeded = true;
+    return;
+  }
+
+  Dali::Vector<uint8_t> buffer;
+
+  if(!mUrl.IsLocalResource())
+  {
+    if(!Dali::FileLoader::DownloadFileSynchronously(mUrl.GetUrl(), buffer))
+    {
+      DALI_LOG_ERROR("Failed to download file! [%s]\n", mUrl.GetUrl().c_str());
+      return;
+    }
+  }
+  else
+  {
+    if(!Dali::FileLoader::ReadFile(mUrl.GetUrl(), buffer))
+    {
+      DALI_LOG_ERROR("Failed to read file! [%s]\n", mUrl.GetUrl().c_str());
+      return;
+    }
+  }
+
+  buffer.PushBack('\0');
+
+  if(!mVectorRenderer.Load(buffer, mDpi))
+  {
+    DALI_LOG_ERROR("Failed to load data! [%s]\n", mUrl.GetUrl().c_str());
+    return;
+  }
+
+  mHasSucceeded = true;
+}
+
+bool SvgLoadingTask::IsReady()
+{
+  return true;
+}
+
+SvgRasterizingTask::SvgRasterizingTask(VectorImageRenderer vectorRenderer, uint32_t width, uint32_t height, CallbackBase* callback)
+: SvgTask(vectorRenderer, callback),
+  mWidth(width),
+  mHeight(height)
+{
+}
+
+SvgRasterizingTask::~SvgRasterizingTask()
+{
+}
+
+void SvgRasterizingTask::Process()
+{
+  if(!mVectorRenderer.IsLoaded())
+  {
+    DALI_LOG_ERROR("File is not loaded!\n");
+    return;
+  }
+
+  Devel::PixelBuffer pixelBuffer = mVectorRenderer.Rasterize(mWidth, mHeight);
+  if(!pixelBuffer)
+  {
+    DALI_LOG_ERROR("Rasterize is failed!\n");
+    return;
+  }
+
+  mPixelData    = Devel::PixelBuffer::Convert(pixelBuffer);
+  mHasSucceeded = true;
+}
+
+bool SvgRasterizingTask::IsReady()
+{
+  return mVectorRenderer.IsLoaded();
+}
+
+PixelData SvgRasterizingTask::GetPixelData() const
+{
+  return mPixelData;
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/svg/svg-task.h b/dali-toolkit/internal/visuals/svg/svg-task.h
new file mode 100644 (file)
index 0000000..31855b9
--- /dev/null
@@ -0,0 +1,200 @@
+#ifndef DALI_TOOLKIT_SVG_TASK_H
+#define DALI_TOOLKIT_SVG_TASK_H
+
+/*
+ * 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.
+ * 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 <dali/devel-api/adaptor-framework/vector-image-renderer.h>
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/images/pixel-data.h>
+#include <memory>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/visuals/visual-url.h>
+#include <dali/public-api/adaptor-framework/async-task-manager.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+class SvgVisual;
+typedef IntrusivePtr<SvgVisual> SvgVisualPtr;
+class SvgTask;
+typedef IntrusivePtr<SvgTask> SvgTaskPtr;
+
+/**
+ * The svg rasterizing tasks to be processed in the worker thread.
+ *
+ * Life cycle of a rasterizing task is as follows:
+ * 1. Created by SvgVisual in the main thread
+ * 2. Queued in the worked thread waiting to be processed.
+ * 3. If this task gets its turn to do the rasterization, it triggers main thread to apply the rasterized image to material then been deleted in main thread call back
+ *    Or if this task is been removed ( new image/size set to the visual or actor off stage) before its turn to be processed, it then been deleted in the worker thread.
+ */
+class SvgTask : public AsyncTask
+{
+public:
+  /**
+   * Constructor
+   * @param[in] vectorRenderer The vector rasterizer.
+   * @param[in] callback The callback that is called when the operation is completed.
+   */
+  SvgTask(VectorImageRenderer vectorRenderer, CallbackBase* callback);
+
+  /**
+   * Destructor.
+   */
+  virtual ~SvgTask() = default;
+
+  /**
+   * Process the task
+   */
+  virtual void Process() = 0;
+
+  /**
+   * Whether the task is ready to process.
+   * @return True if the task is ready to process.
+   */
+  virtual bool IsReady() = 0;
+
+  /**
+   * Whether the task has succeeded.
+   * @return True if the task has succeeded.
+   */
+  bool HasSucceeded() const;
+
+  /**
+   * @brief Get the task's imageRenderer
+   * @return VectorImageRenderer
+   */
+  VectorImageRenderer GetRenderer();
+
+  /**
+   * Get the rasterization result.
+   * @return The pixel data with the rasterized pixels.
+   */
+  virtual PixelData GetPixelData() const;
+
+private:
+  // Undefined
+  SvgTask(const SvgTask& task) = delete;
+
+  // Undefined
+  SvgTask& operator=(const SvgTask& task) = delete;
+
+protected:
+  VectorImageRenderer mVectorRenderer;
+  bool                mHasSucceeded;
+};
+
+class SvgLoadingTask : public SvgTask
+{
+public:
+  /**
+   * Constructor
+   * @param[in] vectorRenderer The vector rasterizer.
+   * @param[in] url The URL to svg resource to use.
+   * @param[in] dpi The DPI of the screen.
+   * @param[in] callback The callback that is called when the operation is completed.
+   */
+  SvgLoadingTask(VectorImageRenderer vectorRenderer, const VisualUrl& url, float dpi, CallbackBase* callback);
+
+  /**
+   * Destructor.
+   */
+  ~SvgLoadingTask() override;
+
+  /**
+   * Process the task
+   */
+  void Process() override;
+
+  /**
+   * Whether the task is ready to process.
+   * @return True if the task is ready to process.
+   */
+  bool IsReady() override;
+
+private:
+  // Undefined
+  SvgLoadingTask(const SvgLoadingTask& task) = delete;
+
+  // Undefined
+  SvgLoadingTask& operator=(const SvgLoadingTask& task) = delete;
+
+private:
+  VisualUrl mUrl;
+  float     mDpi;
+};
+
+class SvgRasterizingTask : public SvgTask
+{
+public:
+  /**
+   * Constructor
+   * @param[in] vectorRenderer The vector rasterizer.
+   * @param[in] width The rasterization width.
+   * @param[in] height The rasterization height.
+   * @param[in] callback The callback that is called when the operation is completed.
+   */
+  SvgRasterizingTask(VectorImageRenderer vectorRenderer, uint32_t width, uint32_t height, CallbackBase* callback);
+
+  /**
+   * Destructor.
+   */
+  ~SvgRasterizingTask() override;
+
+  /**
+   * Process the task accodring to the type
+   */
+  void Process() override;
+
+  /**
+   * Whether the task is ready to process.
+   * @return True if the task is ready to process.
+   */
+  bool IsReady() override;
+
+  /**
+   * Get the rasterization result.
+   * @return The pixel data with the rasterized pixels.
+   */
+  PixelData GetPixelData() const override;
+
+private:
+  // Undefined
+  SvgRasterizingTask(const SvgRasterizingTask& task) = delete;
+
+  // Undefined
+  SvgRasterizingTask& operator=(const SvgRasterizingTask& task) = delete;
+
+private:
+  PixelData mPixelData;
+  uint32_t  mWidth;
+  uint32_t  mHeight;
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_SVG_TASK_H
index cd59107..733141a 100644 (file)
@@ -21,7 +21,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/visuals/image-atlas-manager.h>
 #include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
-#include <dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h>
+#include <dali-toolkit/internal/visuals/svg/svg-task.h>
 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
@@ -93,15 +93,15 @@ void SvgVisual::OnInitialize()
   Vector2 dpi     = Stage::GetCurrent().GetDpi();
   float   meanDpi = (dpi.height + dpi.width) * 0.5f;
 
-  SvgTaskPtr newTask = new SvgLoadingTask(this, mVectorRenderer, mImageUrl, meanDpi);
+  mLoadingTask = new SvgLoadingTask(mVectorRenderer, mImageUrl, meanDpi, MakeCallback(this, &SvgVisual::ApplyRasterizedImage));
 
   if(IsSynchronousLoadingRequired() && mImageUrl.IsLocalResource())
   {
-    newTask->Process();
+    mLoadingTask->Process();
   }
   else
   {
-    mFactoryCache.GetSVGRasterizationManager()->AddTask(newTask);
+    Dali::AsyncTaskManager::Get().AddTask(mLoadingTask);
   }
 }
 
@@ -218,7 +218,11 @@ void SvgVisual::DoSetOnScene(Actor& actor)
 
 void SvgVisual::DoSetOffScene(Actor& actor)
 {
-  mFactoryCache.GetSVGRasterizationManager()->RemoveTask(this);
+  // Remove loading & rasterizing task
+  Dali::AsyncTaskManager::Get().RemoveTask(mLoadingTask);
+  Dali::AsyncTaskManager::Get().RemoveTask(mRasterizingTask);
+  mLoadingTask.Reset();
+  mRasterizingTask.Reset();
 
   actor.RemoveRenderer(mImpl->mRenderer);
   mPlacementActor.Reset();
@@ -291,27 +295,28 @@ void SvgVisual::AddRasterizationTask(const Vector2& size)
     unsigned int width  = static_cast<unsigned int>(size.width);
     unsigned int height = static_cast<unsigned int>(size.height);
 
-    SvgTaskPtr newTask = new SvgRasterizingTask(this, mVectorRenderer, width, height);
+    mRasterizingTask = new SvgRasterizingTask(mVectorRenderer, width, height, MakeCallback(this, &SvgVisual::ApplyRasterizedImage));
 
     if(IsSynchronousLoadingRequired() && mImageUrl.IsLocalResource())
     {
-      newTask->Process();
-      ApplyRasterizedImage(newTask->GetPixelData(), newTask->HasSucceeded());
+      mRasterizingTask->Process();
+      ApplyRasterizedImage(mRasterizingTask);
     }
     else
     {
-      mFactoryCache.GetSVGRasterizationManager()->AddTask(newTask);
+      Dali::AsyncTaskManager::Get().AddTask(mRasterizingTask);
     }
   }
 }
 
-void SvgVisual::ApplyRasterizedImage(PixelData rasterizedPixelData, bool success)
+void SvgVisual::ApplyRasterizedImage(SvgTaskPtr task)
 {
-  if(success)
+  if(task->HasSucceeded())
   {
+    PixelData rasterizedPixelData = task->GetPixelData();
     if(mDefaultWidth == 0 || mDefaultHeight == 0)
     {
-      mVectorRenderer.GetDefaultSize(mDefaultWidth, mDefaultHeight);
+      task->GetRenderer().GetDefaultSize(mDefaultWidth, mDefaultHeight);
     }
 
     // Rasterization success
@@ -382,7 +387,7 @@ void SvgVisual::ApplyRasterizedImage(PixelData rasterizedPixelData, bool success
       ResourceReady(Toolkit::Visual::ResourceStatus::READY);
     }
   }
-  else if(!success && !mLoadFailed)
+  else if(!mLoadFailed)
   {
     mLoadFailed = true;
 
index 93decde..faf8a22 100644 (file)
@@ -25,6 +25,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
 #include <dali-toolkit/internal/visuals/visual-url.h>
+#include <dali-toolkit/internal/visuals/svg/svg-task.h>
 
 namespace Dali
 {
@@ -153,10 +154,9 @@ public:
   /**
    * @bried Apply the rasterized image to the visual.
    *
-   * @param[in] rasterizedPixelData The pixel buffer with the rasterized pixels
-   * @param[in] success Whether the task succeeds.
+   * @param[in] task SvgTaskPtr
    */
-  void ApplyRasterizedImage(PixelData rasterizedPixelData, bool success);
+  void ApplyRasterizedImage(SvgTaskPtr task);
 
 private:
   /**
@@ -189,6 +189,8 @@ private:
   WeakHandle<Actor>         mPlacementActor;
   Vector2                   mRasterizedSize;
   Dali::ImageDimensions     mDesiredSize{};
+  SvgTaskPtr                mLoadingTask;
+  SvgTaskPtr                mRasterizingTask;
   bool                      mLoadFailed;
   bool                      mAttemptAtlasing; ///< If true will attempt atlasing, otherwise create unique texture
 };
index 6b4bf10..6bf66cb 100644 (file)
@@ -43,8 +43,7 @@ const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
 }
 
 VisualFactoryCache::VisualFactoryCache(bool preMultiplyOnLoad)
-: mSvgRasterizeManager(nullptr),
-  mVectorAnimationManager(nullptr),
+: mVectorAnimationManager(nullptr),
   mPreMultiplyOnLoad(preMultiplyOnLoad),
   mBrokenImageInfoContainer(),
   mDefaultBrokenImageUrl(""),
@@ -130,15 +129,6 @@ NPatchLoader& VisualFactoryCache::GetNPatchLoader()
   return mNPatchLoader;
 }
 
-SvgRasterizeManager* VisualFactoryCache::GetSVGRasterizationManager()
-{
-  if(!mSvgRasterizeManager)
-  {
-    mSvgRasterizeManager = std::unique_ptr<SvgRasterizeManager>(new SvgRasterizeManager());
-  }
-  return mSvgRasterizeManager.get();
-}
-
 VectorAnimationManager& VisualFactoryCache::GetVectorAnimationManager()
 {
   if(!mVectorAnimationManager)
index 0edda01..43fee4c 100644 (file)
@@ -27,7 +27,6 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/texture-manager/texture-manager-impl.h>
 #include <dali-toolkit/internal/visuals/npatch-loader.h>
-#include <dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h>
 #include <dali/devel-api/rendering/renderer-devel.h>
 
 namespace Dali
@@ -245,12 +244,6 @@ public:
   NPatchLoader& GetNPatchLoader();
 
   /**
-   * Get the SVG rasterization manager.
-   * @return A raw pointer pointing to the SVG rasterization manager.
-   */
-  SvgRasterizeManager* GetSVGRasterizationManager();
-
-  /**
    * Get the vector animation manager.
    * @return A reference to the vector animation manager.
    */
@@ -348,7 +341,6 @@ private:
   TextureManager       mTextureManager;
   NPatchLoader         mNPatchLoader;
 
-  std::unique_ptr<SvgRasterizeManager>    mSvgRasterizeManager;
   std::unique_ptr<VectorAnimationManager> mVectorAnimationManager;
   bool                                    mPreMultiplyOnLoad;
   std::vector<BrokenImageInfo>            mBrokenImageInfoContainer;