Generate url and load texture from encoded image buffer 15/259415/24
authorEunki, Hong <eunkiki.hong@samsung.com>
Tue, 8 Jun 2021 06:07:20 +0000 (15:07 +0900)
committerEunki Hong <eunkiki.hong@samsung.com>
Mon, 26 Jul 2021 08:33:29 +0000 (01:33 -0700)
Make some way to load image from raw-buffer stream.
This raw-buffer will alive when some actor contain this buffer.

Limitation : animated-image, vector-image, animated-vector-image not working now. Will support another patch

1. Generate url from encoded raw buffer like this
  ImageUrl url = Toolkit::Image::GenerateUrl(const EncodedImageBuffer &);
2. When we use URL as this string, we can load it like normal LOCAL file.
  ImageView imageView = Toolkit::ImageView::New(url.GetUrl());
3. Buffer will automatically removed when ImageUrl scope is out-of-date, and no actor use it.

NOTE : even ImageUrl lifecycle is done, cached texture can use internally.

Change-Id: I517d9526d13a6b761792dcb7054864643f209b67
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
25 files changed:
automated-tests/src/dali-toolkit-internal/CMakeLists.txt
automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-VisualUrl.cpp
automated-tests/src/dali-toolkit/CMakeLists.txt
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-encoded-image-buffer.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-encoded-image-buffer.h [new file with mode: 0644]
automated-tests/src/dali-toolkit/utc-Dali-Image.cpp
automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp
automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp
dali-toolkit/devel-api/image-loader/image-atlas.h
dali-toolkit/internal/image-loader/async-image-loader-impl.cpp
dali-toolkit/internal/image-loader/image-load-thread.cpp
dali-toolkit/internal/image-loader/image-load-thread.h
dali-toolkit/internal/image-loader/image-url-impl.cpp
dali-toolkit/internal/image-loader/image-url-impl.h
dali-toolkit/internal/visuals/image/image-visual.cpp
dali-toolkit/internal/visuals/npatch/npatch-visual.cpp
dali-toolkit/internal/visuals/texture-manager-impl.cpp
dali-toolkit/internal/visuals/texture-manager-impl.h
dali-toolkit/internal/visuals/visual-url.cpp
dali-toolkit/internal/visuals/visual-url.h
dali-toolkit/public-api/image-loader/image-url.cpp
dali-toolkit/public-api/image-loader/image-url.h
dali-toolkit/public-api/image-loader/image.cpp
dali-toolkit/public-api/image-loader/image.h

index d50921c..c1b0ae6 100755 (executable)
@@ -80,6 +80,7 @@ SET(TEST_HARNESS_SOURCES
    ../dali-toolkit/dali-toolkit-test-utils/test-animation-data.cpp
    ../dali-toolkit/dali-toolkit-test-utils/test-application.cpp
    ../dali-toolkit/dali-toolkit-test-utils/test-button.cpp
+   ../dali-toolkit/dali-toolkit-test-utils/test-encoded-image-buffer.cpp
    ../dali-toolkit/dali-toolkit-test-utils/test-harness.cpp
    ../dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.cpp
    ../dali-toolkit/dali-toolkit-test-utils/test-graphics-sync-impl.cpp
index 9098be8..04c51af 100644 (file)
@@ -26,6 +26,9 @@
 #include <dali-toolkit/internal/visuals/texture-upload-observer.h>
 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
 #include <dali-toolkit/internal/visuals/image-atlas-manager.h>
+#include <dali-toolkit/internal/visuals/visual-factory-impl.h> ///< For VisualFactory's member TextureManager.
+
+#include <test-encoded-image-buffer.h>
 
 #if defined(ELDBUS_ENABLED)
 #include <automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/dbus-wrapper.h>
@@ -147,6 +150,315 @@ int UtcTextureManagerGenerateHash(void)
   END_TEST;
 }
 
+int UtcTextureManagerEncodedImageBuffer(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline( "UtcTextureManagerEncodedImageBuffer" );
+
+  auto  visualFactory  = Toolkit::VisualFactory::Get();
+  auto& textureManager = GetImplementation(visualFactory).GetTextureManager(); // Use VisualFactory's texture manager
+
+  // Get encoded raw-buffer image and generate url
+  EncodedImageBuffer buffer1 = ConvertFileToEncodedImageBuffer(TEST_IMAGE_FILE_NAME);
+  EncodedImageBuffer buffer2 = ConvertFileToEncodedImageBuffer(TEST_IMAGE_FILE_NAME);
+
+  std::string  url1 = textureManager.AddExternalEncodedImageBuffer(buffer1);
+  std::string  url2 = textureManager.AddExternalEncodedImageBuffer(buffer1);
+  std::string  url3 = VisualUrl::CreateBufferUrl(""); ///< Impossible Buffer URL. for coverage
+
+  // Check if same EncodedImageBuffer get same url
+  DALI_TEST_CHECK(url1 == url2);
+  // Reduce reference count
+  textureManager.RemoveExternalEncodedImageBuffer(url1);
+  // Check whethere url1 still valid
+  DALI_TEST_CHECK(textureManager.GetEncodedImageBuffer(url1));
+
+  url2 = textureManager.AddExternalEncodedImageBuffer(buffer2);
+  // Check if difference EncodedImageBuffer get difference url
+  DALI_TEST_CHECK(url1 != url2);
+
+  auto preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+
+  TestObserver observer1;
+  textureManager.RequestLoad(
+    url1,
+    ImageDimensions(),
+    FittingMode::SCALE_TO_FILL,
+    SamplingMode::BOX_THEN_LINEAR,
+    TextureManager::NO_ATLAS,
+    &observer1,
+    true, ///< orientationCorrection
+    TextureManager::ReloadPolicy::CACHED,
+    preMultiply);
+
+  DALI_TEST_EQUALS( observer1.mLoaded, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( observer1.mObserverCalled, false, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( observer1.mLoaded, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( observer1.mObserverCalled, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( observer1.mCompleteType, TestObserver::CompleteType::UPLOAD_COMPLETE, TEST_LOCATION );
+
+  TestObserver observer2;
+  // Syncload
+  Devel::PixelBuffer pixelBuffer = textureManager.LoadPixelBuffer(
+    url2,
+    ImageDimensions(),
+    FittingMode::SCALE_TO_FILL,
+    SamplingMode::BOX_THEN_LINEAR,
+    true, ///< synchronousLoading
+    &observer2,
+    true, ///< orientationCorrection
+    preMultiply);
+
+  DALI_TEST_CHECK( pixelBuffer );
+  DALI_TEST_EQUALS( observer2.mLoaded, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( observer2.mObserverCalled, false, TEST_LOCATION );
+
+  // Asyncload
+  pixelBuffer = textureManager.LoadPixelBuffer(
+    url2,
+    ImageDimensions(),
+    FittingMode::SCALE_TO_FILL,
+    SamplingMode::BOX_THEN_LINEAR,
+    false, ///< synchronousLoading
+    &observer2,
+    true, ///< orientationCorrection
+    preMultiply);
+
+  DALI_TEST_EQUALS( observer2.mLoaded, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( observer2.mObserverCalled, false, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( observer2.mLoaded, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( observer2.mObserverCalled, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( observer2.mCompleteType, TestObserver::CompleteType::LOAD_COMPLETE, TEST_LOCATION );
+
+  textureManager.RemoveExternalEncodedImageBuffer(url1);
+  textureManager.RemoveExternalEncodedImageBuffer(url2);
+
+  // Now url1 and url2 is invalid type. mLoaded will return false
+
+  TestObserver observer3;
+  textureManager.RequestLoad(
+    url1,
+    ImageDimensions(),
+    FittingMode::SCALE_TO_FILL,
+    SamplingMode::BOX_THEN_LINEAR,
+    TextureManager::NO_ATLAS,
+    &observer3,
+    true, ///< orientationCorrection
+    TextureManager::ReloadPolicy::CACHED,
+    preMultiply);
+
+  // Load will be success because url1 is cached
+  DALI_TEST_EQUALS( observer3.mLoaded, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( observer3.mObserverCalled, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( observer3.mCompleteType, TestObserver::CompleteType::UPLOAD_COMPLETE, TEST_LOCATION );
+
+  TestObserver observer4;
+  textureManager.RequestLoad(
+    url2,
+    ImageDimensions(),
+    FittingMode::SCALE_TO_FILL,
+    SamplingMode::BOX_THEN_LINEAR,
+    TextureManager::NO_ATLAS,
+    &observer4,
+    true, ///< orientationCorrection
+    TextureManager::ReloadPolicy::FORCED,
+    preMultiply);
+
+  DALI_TEST_EQUALS( observer4.mLoaded, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( observer4.mObserverCalled, false, TEST_LOCATION );
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render();
+
+  // Load will be failed becuase reloadpolicy is forced
+  DALI_TEST_EQUALS( observer4.mLoaded, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( observer4.mObserverCalled, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( observer4.mCompleteType, TestObserver::CompleteType::UPLOAD_COMPLETE, TEST_LOCATION );
+
+  TestObserver observer5;
+  pixelBuffer = textureManager.LoadPixelBuffer(
+    url2,
+    ImageDimensions(),
+    FittingMode::SCALE_TO_FILL,
+    SamplingMode::BOX_THEN_LINEAR,
+    true, ///< synchronousLoading
+    &observer5,
+    true, ///< orientationCorrection
+    preMultiply);
+
+  // Load will be faild because synchronousLoading doesn't use cached texture
+  DALI_TEST_CHECK( !pixelBuffer );
+  DALI_TEST_EQUALS( observer5.mLoaded, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( observer5.mObserverCalled, false, TEST_LOCATION );
+
+  TestObserver observer6;
+  pixelBuffer = textureManager.LoadPixelBuffer(
+    url3,
+    ImageDimensions(),
+    FittingMode::SCALE_TO_FILL,
+    SamplingMode::BOX_THEN_LINEAR,
+    false, ///< synchronousLoading
+    &observer6,
+    true, ///< orientationCorrection
+    preMultiply);
+
+  DALI_TEST_EQUALS( observer6.mLoaded, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( observer6.mObserverCalled, false, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render();
+
+  // Load will be failed because url3 is invalid URL
+  DALI_TEST_EQUALS( observer6.mLoaded, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( observer6.mObserverCalled, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( observer6.mCompleteType, TestObserver::CompleteType::LOAD_COMPLETE, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcTextureManagerEncodedImageBufferReferenceCount(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline( "UtcTextureManagerEncodedImageBuffer check reference count works well" );
+
+  auto  visualFactory  = Toolkit::VisualFactory::Get();
+  auto& textureManager = GetImplementation(visualFactory).GetTextureManager(); // Use VisualFactory's texture manager
+
+  // Get encoded raw-buffer image and generate url
+  EncodedImageBuffer buffer1 = ConvertFileToEncodedImageBuffer(TEST_IMAGE_FILE_NAME);
+  EncodedImageBuffer buffer2 = ConvertFileToEncodedImageBuffer(TEST_IMAGE_FILE_NAME);
+
+  std::string  url1    = textureManager.AddExternalEncodedImageBuffer(buffer1);
+  std::string  url2    = textureManager.AddExternalEncodedImageBuffer(buffer1);
+
+  // Check if same EncodedImageBuffer get same url
+  DALI_TEST_CHECK(url1 == url2);
+
+  // Reduce reference count
+  textureManager.RemoveExternalEncodedImageBuffer(url1);
+  // Check whethere url1 still valid
+  DALI_TEST_CHECK(textureManager.GetEncodedImageBuffer(url1));
+
+  // Reduce reference count
+  textureManager.RemoveExternalEncodedImageBuffer(url1);
+  // Check whethere url1 is not valid anymore
+  DALI_TEST_CHECK(!textureManager.GetEncodedImageBuffer(url1));
+
+  // UseExternalTexture doesn't create new buffer.
+  // So, reference count is still zero.
+  textureManager.UseExternalResource(url1);
+  DALI_TEST_CHECK(!textureManager.GetEncodedImageBuffer(url1));
+
+  url1 = textureManager.AddExternalEncodedImageBuffer(buffer1);
+  // Check if difference EncodedImageBuffer get difference url
+  // Previous EncodedImageBuffer was deleted, so we get new url even same buffer.
+  DALI_TEST_CHECK(url1 != url2);
+
+  url2 = textureManager.AddExternalEncodedImageBuffer(buffer2);
+  // Check if difference EncodedImageBuffer get difference url
+  DALI_TEST_CHECK(url1 != url2);
+
+  auto preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+
+  // url1 load image by cache
+  TestObserver observer1;
+  textureManager.RequestLoad(
+    url1,
+    ImageDimensions(),
+    FittingMode::SCALE_TO_FILL,
+    SamplingMode::BOX_THEN_LINEAR,
+    TextureManager::NO_ATLAS,
+    &observer1,
+    true, ///< orientationCorrection
+    TextureManager::ReloadPolicy::CACHED,
+    preMultiply);
+
+  DALI_TEST_EQUALS( observer1.mLoaded, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( observer1.mObserverCalled, false, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( observer1.mLoaded, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( observer1.mObserverCalled, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( observer1.mCompleteType, TestObserver::CompleteType::UPLOAD_COMPLETE, TEST_LOCATION );
+
+  // LoadPixelBuffer doen't use cache. url2 will not be cached
+  TestObserver observer2;
+  Devel::PixelBuffer pixelBuffer = textureManager.LoadPixelBuffer(
+    url2,
+    ImageDimensions(),
+    FittingMode::SCALE_TO_FILL,
+    SamplingMode::BOX_THEN_LINEAR,
+    false, ///< synchronousLoading
+    &observer2,
+    true, ///< orientationCorrection
+    preMultiply);
+
+  DALI_TEST_EQUALS( observer2.mLoaded, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( observer2.mObserverCalled, false, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( observer2.mLoaded, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( observer2.mObserverCalled, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( observer2.mCompleteType, TestObserver::CompleteType::LOAD_COMPLETE, TEST_LOCATION );
+
+  // Decrease each url's reference count.
+  textureManager.RemoveExternalEncodedImageBuffer(url1);
+  textureManager.RemoveExternalEncodedImageBuffer(url2);
+
+  // url1 buffer is still have 1 reference count because it is cached.
+  // But url2 not valid because it is not cached.
+  DALI_TEST_CHECK(textureManager.GetEncodedImageBuffer(url1));
+  DALI_TEST_CHECK(!textureManager.GetEncodedImageBuffer(url2));
+
+  // Check url1 buffer have 1 reference count because it is cached.
+  textureManager.RemoveExternalEncodedImageBuffer(url1);
+  DALI_TEST_CHECK(!textureManager.GetEncodedImageBuffer(url1));
+
+  END_TEST;
+}
+
+
 int UtcTextureManagerCachingForDifferentLoadingType(void)
 {
   ToolkitTestApplication application;
index c57ec89..767c1f8 100644 (file)
@@ -54,6 +54,18 @@ int UtcDaliVisualUrlConstructor(void)
   DALI_TEST_EQUALS( true, visualUrl4.IsValid(), TEST_LOCATION );
   DALI_TEST_EQUALS( visualUrl4.GetType(), VisualUrl::REGULAR_IMAGE, TEST_LOCATION );
   DALI_TEST_EQUALS( visualUrl4.GetProtocolType(), VisualUrl::TEXTURE, TEST_LOCATION );
+
+  VisualUrl visualUrl6("enbuf://0");
+  visualUrl6 = visualUrl;
+  DALI_TEST_EQUALS( true, visualUrl6.IsValid(), TEST_LOCATION );
+  DALI_TEST_EQUALS( visualUrl6.GetType(), VisualUrl::GIF, TEST_LOCATION );
+  DALI_TEST_EQUALS( visualUrl6.GetProtocolType(), VisualUrl::LOCAL, TEST_LOCATION );
+
+  VisualUrl visualUrl7("enbuf://1");
+  visualUrl6 = visualUrl7;
+  DALI_TEST_EQUALS( true, visualUrl6.IsValid(), TEST_LOCATION );
+  DALI_TEST_EQUALS( visualUrl6.GetType(), VisualUrl::REGULAR_IMAGE, TEST_LOCATION );
+  DALI_TEST_EQUALS( visualUrl6.GetProtocolType(), VisualUrl::BUFFER, TEST_LOCATION );
   END_TEST;
 }
 
@@ -233,6 +245,15 @@ int UtcDaliVisualUrlLocationP(void)
   DALI_TEST_EQUALS( VisualUrl::TEXTURE, VisualUrl("dali://bar.org/foobar.svg").GetProtocolType(), TEST_LOCATION );
   DALI_TEST_EQUALS( VisualUrl::TEXTURE, VisualUrl("dali://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION );
 
+  DALI_TEST_EQUALS( VisualUrl::BUFFER, VisualUrl("enbuf://").GetProtocolType(), TEST_LOCATION );
+  DALI_TEST_EQUALS( VisualUrl::BUFFER, VisualUrl("enbuf://1234").GetProtocolType(), TEST_LOCATION );
+  DALI_TEST_EQUALS( VisualUrl::BUFFER, VisualUrl("ENBUF://1234").GetProtocolType(), TEST_LOCATION );
+  DALI_TEST_EQUALS( VisualUrl::BUFFER, VisualUrl("enbuf://.gif").GetProtocolType(), TEST_LOCATION );
+  DALI_TEST_EQUALS( VisualUrl::BUFFER, VisualUrl("enbuf://bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION );
+  DALI_TEST_EQUALS( VisualUrl::BUFFER, VisualUrl("enbuf://bar.org/foobar.png").GetProtocolType(), TEST_LOCATION );
+  DALI_TEST_EQUALS( VisualUrl::BUFFER, VisualUrl("enbuf://bar.org/foobar.svg").GetProtocolType(), TEST_LOCATION );
+  DALI_TEST_EQUALS( VisualUrl::BUFFER, VisualUrl("enbuf://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION );
+
   END_TEST;
 }
 
@@ -262,6 +283,8 @@ int UtcDaliVisualUrlLocationN(void)
   DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("ssh:a/bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION );
   DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("shh://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION );
   DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("sss://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION );
+  DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("fsh://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION );
+  DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("stp://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION );
   DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("http:/bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION );
   DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("h1tps://bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION );
   DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("ht2ps://bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION );
@@ -280,6 +303,18 @@ int UtcDaliVisualUrlLocationN(void)
   DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("dali:5/1").GetProtocolType(), TEST_LOCATION );
   DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("dali:/61").GetProtocolType(), TEST_LOCATION );
 
+  DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("eunki://1").GetProtocolType(), TEST_LOCATION );
+  DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("enbu://1").GetProtocolType(), TEST_LOCATION );
+  DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("eubnf://1").GetProtocolType(), TEST_LOCATION );
+  DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("1nbuf://1").GetProtocolType(), TEST_LOCATION );
+  DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("e2bun://1").GetProtocolType(), TEST_LOCATION );
+  DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("en3uf://1").GetProtocolType(), TEST_LOCATION );
+  DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("enb4f://1").GetProtocolType(), TEST_LOCATION );
+  DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("enbu5://1").GetProtocolType(), TEST_LOCATION );
+  DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("enbuf6//1").GetProtocolType(), TEST_LOCATION );
+  DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("enbuf:7/1").GetProtocolType(), TEST_LOCATION );
+  DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("enbuf:/81").GetProtocolType(), TEST_LOCATION );
+
   END_TEST;
 }
 
@@ -367,6 +402,7 @@ int UtcDaliVisualUrlGetLocationP(void)
 
   DALI_TEST_EQUAL( "a", VisualUrl("http://a").GetLocation() );
   DALI_TEST_EQUAL( "1", VisualUrl("dali://1").GetLocation() );
+  DALI_TEST_EQUAL( "4", VisualUrl("enbuf://4").GetLocation() );
   DALI_TEST_EQUAL( "", VisualUrl("ftp://").GetLocation() );
   DALI_TEST_EQUAL( "http://", VisualUrl("http://http://").GetLocation() );
 
@@ -381,6 +417,7 @@ int UtcDaliVisualUrlGetLocationN(void)
   DALI_TEST_EQUAL( "a", VisualUrl("a").GetLocation() );
   DALI_TEST_EQUAL( "dali:/1", VisualUrl("dali:/1").GetLocation() );
   DALI_TEST_EQUAL( "dali//1", VisualUrl("dali//1").GetLocation() );
+  DALI_TEST_EQUAL( "enbuf:/2", VisualUrl("enbuf:/2").GetLocation() );
   DALI_TEST_EQUAL( "", VisualUrl("http:/http://").GetLocation() );
 
   END_TEST;
@@ -396,3 +433,14 @@ int UtcDaliVisualUrlCreateTextureUrl(void)
 
   END_TEST;
 }
+
+int UtcDaliVisualUrlCreateBufferUrl(void)
+{
+  tet_infoline( "UtcDaliVisualUrl CreateBufferUrl" );
+
+  DALI_TEST_EQUAL( "enbuf://a", VisualUrl::CreateBufferUrl( "a" ) );
+  DALI_TEST_EQUAL( "enbuf://1234", VisualUrl::CreateBufferUrl( "1234" ) );
+  DALI_TEST_EQUAL( "enbuf://", VisualUrl::CreateBufferUrl( "" ) );
+
+  END_TEST;
+}
index 0e984f0..b3c04d4 100755 (executable)
@@ -112,6 +112,7 @@ SET(TEST_HARNESS_SOURCES
   dali-toolkit-test-utils/test-animation-data.cpp
   dali-toolkit-test-utils/test-application.cpp
   dali-toolkit-test-utils/test-button.cpp
+  dali-toolkit-test-utils/test-encoded-image-buffer.cpp
   dali-toolkit-test-utils/test-harness.cpp
   dali-toolkit-test-utils/test-gesture-generator.cpp
   dali-toolkit-test-utils/test-gl-abstraction.cpp
diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-encoded-image-buffer.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-encoded-image-buffer.cpp
new file mode 100644 (file)
index 0000000..e693098
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ *
+ */
+
+#include "test-application.h"
+
+#include "test-encoded-image-buffer.h"
+
+namespace Dali
+{
+EncodedImageBuffer ConvertFileToEncodedImageBuffer(const char* url)
+{
+  EncodedImageBuffer buffer;
+  FILE *fp;
+  fp = fopen(url, "rb");
+  if(fp != NULL)
+  {
+    fseek(fp, 0, SEEK_END);
+    size_t size = ftell(fp);
+    Dali::Vector<uint8_t> data;
+    data.Resize(size);
+    fseek(fp, 0, SEEK_SET);
+    fread(data.Begin(), size, sizeof(uint8_t), fp);
+    fclose(fp);
+    buffer = EncodedImageBuffer::New(data);
+  }
+  return buffer;
+}
+
+} // namespace Dali
diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-encoded-image-buffer.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-encoded-image-buffer.h
new file mode 100644 (file)
index 0000000..96fbe46
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef TEST_ENCODED_IMAGE_BUFFER_H
+#define TEST_ENCODED_IMAGE_BUFFER_H
+
+/*
+ * 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.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
+
+namespace Dali
+{
+
+// util function to convert local file to EncodedImageBuffer
+EncodedImageBuffer ConvertFileToEncodedImageBuffer(const char* url);
+
+} // namespace Dali
+
+#endif // TEST_ENCODED_IMAGE_BUFFER_H
index 37e3b5e..b4b88b6 100644 (file)
@@ -122,3 +122,18 @@ int UtcDaliImageConvertNativeImageSourceToUrl(void)
 
   END_TEST;
 }
+
+int UtcDaliImageConvertEncodedImageBufferToUrl(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline( "UtcDaliImageConvertEncodedImageBufferToUrl" );
+
+  Dali::Vector<uint8_t> buffer;
+  buffer.PushBack(0x11);
+  buffer.PushBack(0x22);
+  buffer.PushBack(0x33);
+
+  DALI_TEST_CHECK( Dali::Toolkit::Image::GenerateUrl( EncodedImageBuffer::New(buffer) ).GetUrl().size() > 0u );
+
+  END_TEST;
+}
index 1cd3de5..0450040 100644 (file)
 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
 #include <dali-toolkit/devel-api/visuals/image-visual-actions-devel.h>
 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
+#include <dali-toolkit/public-api/image-loader/image.h>
+#include <dali-toolkit/public-api/image-loader/image-url.h>
 
 #include <test-native-image.h>
+#include <test-encoded-image-buffer.h>
 #include <sstream>
 #include <unistd.h>
 
@@ -534,8 +537,6 @@ int UtcDaliImageViewAsyncLoadingWithoutAltasing(void)
   const std::vector<GLuint>& textures2 = gl.GetBoundTextures();
   DALI_TEST_GREATER( textures2.size(), numTextures, TEST_LOCATION );
 
-
-
   END_TEST;
 }
 
@@ -713,6 +714,150 @@ int UtcDaliImageViewSyncLoading02(void)
   END_TEST;
 }
 
+int UtcDaliImageViewAsyncLoadingEncodedBuffer(void)
+{
+  ToolkitTestApplication application;
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+  const std::vector<GLuint>& textures = gl.GetBoundTextures();
+  size_t numTextures = textures.size();
+
+  // Get encoded raw-buffer image and generate url
+  EncodedImageBuffer buffer = ConvertFileToEncodedImageBuffer(gImage_600_RGB);
+  ImageUrl           url    = Toolkit::Image::GenerateUrl(buffer);
+
+  // Async loading, no atlasing for big size image
+  ImageView imageView = ImageView::New(url.GetUrl());
+
+  // By default, Aysnc loading is used
+  application.GetScene().Add(imageView);
+  imageView.SetProperty( Actor::Property::SIZE, Vector2(100, 100) );
+  imageView.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
+
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+
+  const std::vector<GLuint>& textures2 = gl.GetBoundTextures();
+  DALI_TEST_GREATER( textures2.size(), numTextures, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliImageViewAsyncLoadingEncodedBufferWithAtlasing(void)
+{
+  ToolkitTestApplication application;
+
+  // Get encoded raw-buffer image and generate url
+  EncodedImageBuffer buffer = ConvertFileToEncodedImageBuffer(gImage_600_RGB);
+  ImageUrl           url    = Toolkit::Image::GenerateUrl(buffer);
+  ImageUrl           url2   = Toolkit::Image::GenerateUrl(buffer);
+
+  // Generate url is not equal to url2
+  // NOTE : This behavior may changed when ImageUrl compare operator changed.
+  DALI_TEST_CHECK(url != url2);
+  // Generate url's string is equal to url2's string
+  DALI_TEST_CHECK(url.GetUrl() == url2.GetUrl());
+
+  EncodedImageBuffer buffer2 = ConvertFileToEncodedImageBuffer(gImage_600_RGB);
+  url2 = Toolkit::Image::GenerateUrl(buffer2);
+
+  // Check whethere two url are not equal
+  DALI_TEST_CHECK(url.GetUrl() != url2.GetUrl());
+
+  // Async loading, automatic atlasing for small size image
+  TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace();
+  callStack.Reset();
+  callStack.Enable(true);
+
+  Property::Map imageMap;
+
+  imageMap[ ImageVisual::Property::URL ] = url.GetUrl();
+  imageMap[ ImageVisual::Property::DESIRED_HEIGHT ] = 34;
+  imageMap[ ImageVisual::Property::DESIRED_WIDTH ] = 34;
+  imageMap[ ImageVisual::Property::ATLASING] = true;
+
+  ImageView imageView = ImageView::New();
+  imageView.SetProperty( ImageView::Property::IMAGE, imageMap );
+  imageView.SetProperty( Toolkit::Control::Property::PADDING, Extents( 10u, 10u, 10u, 10u ) );
+
+  // By default, Aysnc loading is used
+  // loading is not started if the actor is offScene
+
+  application.GetScene().Add( imageView );
+  application.SendNotification();
+  application.Render(16);
+  application.Render(16);
+  application.SendNotification();
+
+  // Change url to url2
+  imageMap[ ImageVisual::Property::URL ] = url2.GetUrl();
+  imageView.SetProperty( ImageView::Property::IMAGE, imageMap );
+
+  imageView.SetProperty( Dali::Actor::Property::LAYOUT_DIRECTION,  Dali::LayoutDirection::RIGHT_TO_LEFT );
+  application.SendNotification();
+  application.Render(16);
+  application.Render(16);
+  application.SendNotification();
+
+  // loading started, this waits for the loader thread for max 30 seconds
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(16);
+
+  callStack.Enable(false);
+
+  TraceCallStack::NamedParams params;
+  params["width"] << 34;
+  params["height"] << 34;
+  DALI_TEST_EQUALS( callStack.FindMethodAndParams( "TexSubImage2D", params ), true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliImageViewSyncLoadingEncodedBuffer(void)
+{
+  ToolkitTestApplication application;
+
+  tet_infoline("ImageView Testing sync loading from EncodedImageBuffer");
+
+  // Get encoded raw-buffer image and generate url
+  EncodedImageBuffer buffer = ConvertFileToEncodedImageBuffer(gImage_34_RGBA);
+  ImageUrl           url    = Toolkit::Image::GenerateUrl(buffer);
+
+  // Sync loading, automatic atlasing for small size image
+  {
+    TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace();
+    callStack.Reset();
+    callStack.Enable(true);
+
+    ImageView imageView = ImageView::New( );
+
+    // Sync loading is used
+    Property::Map syncLoadingMap;
+    syncLoadingMap[ "url" ] = url.GetUrl();
+    syncLoadingMap[ "desiredHeight" ] = 34;
+    syncLoadingMap[ "desiredWidth" ] = 34;
+    syncLoadingMap[ "synchronousLoading" ] = true;
+    syncLoadingMap[ "atlasing" ] = true;
+    imageView.SetProperty( ImageView::Property::IMAGE, syncLoadingMap );
+
+    application.GetScene().Add( imageView );
+    application.SendNotification();
+    application.Render(16);
+
+    TraceCallStack::NamedParams params;
+    params["width"] << 34;
+    params["height"] << 34;
+    DALI_TEST_EQUALS( callStack.FindMethodAndParams( "TexSubImage2D", params ),
+                      true, TEST_LOCATION );
+  }
+
+  END_TEST;
+}
+
 int UtcDaliImageViewAddedTexture(void)
 {
   ToolkitTestApplication application;
index 40ca439..1dbb737 100644 (file)
 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
 #include <dali-toolkit/devel-api/controls/control-devel.h>
 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
+#include <dali-toolkit/devel-api/image-loader/texture-manager.h>
 #include <dali-toolkit/public-api/image-loader/image.h>
 #include <dali-toolkit/public-api/image-loader/image-url.h>
 #include <dali-toolkit/dali-toolkit.h>
+
+#include <test-encoded-image-buffer.h>
 #include "dummy-control.h"
 
 using namespace Dali;
@@ -520,6 +523,106 @@ int UtcDaliImageVisualWithNativeImageRemoved(void)
   END_TEST;
 }
 
+int UtcDaliImageVisualWithEncodedImageBuffer(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline( "Use Encoded Image Buffer as url" );
+
+  EncodedImageBuffer rawBuffer = ConvertFileToEncodedImageBuffer(TEST_LARGE_IMAGE_FILE_NAME);
+  ImageUrl url = Dali::Toolkit::Image::GenerateUrl(rawBuffer);
+
+  VisualFactory factory = VisualFactory::Get();
+  DALI_TEST_CHECK( factory );
+
+  Property::Map propertyMap;
+  propertyMap.Insert( Toolkit::Visual::Property::TYPE, Visual::IMAGE );
+  propertyMap.Insert( ImageVisual::Property::URL, url.GetUrl() );
+
+  Visual::Base visual = factory.CreateVisual( propertyMap );
+  DALI_TEST_CHECK( visual );
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+  TraceCallStack& textureTrace = gl.GetTextureTrace();
+  textureTrace.Enable(true);
+
+  DummyControl actor = DummyControl::New();
+  DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+  dummyImpl.RegisterVisual( Control::CONTROL_PROPERTY_END_INDEX + 1, visual );
+
+  actor.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) );
+  DALI_TEST_EQUALS( actor.GetRendererCount(), 0u, TEST_LOCATION );
+
+  application.GetScene().Add( actor );
+  application.SendNotification();
+
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( actor.GetRendererCount(), 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( textureTrace.FindMethod("BindTexture"), true, TEST_LOCATION );
+
+  application.GetScene().Remove( actor );
+  DALI_TEST_CHECK( actor.GetRendererCount() == 0u );
+
+  END_TEST;
+}
+
+int UtcDaliImageVisualWithEncodedImageBufferRemoved(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline( "Use Encoded Image Buffer as url" );
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+  TraceCallStack& textureTrace = gl.GetTextureTrace();
+  textureTrace.Enable(true);
+
+  EncodedImageBuffer rawBuffer = ConvertFileToEncodedImageBuffer(TEST_LARGE_IMAGE_FILE_NAME);
+  ImageUrl imageUrl = Dali::Toolkit::Image::GenerateUrl(rawBuffer);
+  std::string url = imageUrl.GetUrl();
+
+  VisualFactory factory = VisualFactory::Get();
+  DALI_TEST_CHECK( factory );
+
+  Property::Map propertyMap;
+  propertyMap.Insert( Toolkit::Visual::Property::TYPE,  Visual::IMAGE );
+  propertyMap.Insert( ImageVisual::Property::URL,  url );
+
+  Visual::Base visual = factory.CreateVisual( propertyMap );
+  DALI_TEST_CHECK( visual );
+
+  DummyControl actor = DummyControl::New();
+  DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+  dummyImpl.RegisterVisual(  DummyControl::Property::TEST_VISUAL, visual );
+
+  DALI_TEST_EQUALS( actor.GetRendererCount(), 0u, TEST_LOCATION );
+
+  application.GetScene().Add( actor );
+  application.SendNotification();
+
+  // Wait for decode buffer and make texture.
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( actor.GetRendererCount(), 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( textureTrace.CountMethod("DeleteTextures"), 0, TEST_LOCATION );
+
+  tet_infoline( "Delete texture because there is no actor to use decoded texture" );
+  imageUrl.Reset();
+  application.GetScene().Remove( actor );
+  dummyImpl.UnregisterVisual( DummyControl::Property::TEST_VISUAL );
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( actor.GetRendererCount(), 0u, TEST_LOCATION );
+  DALI_TEST_EQUALS( textureTrace.CountMethod("DeleteTextures"), 1, TEST_LOCATION );
+
+  END_TEST;
+}
+
 int UtcDaliImageVisualTextureReuse1(void)
 {
   ToolkitTestApplication application;
index af3cc41..a1a3c49 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef DALI_TOOLKIT_IMAGE_ATLAS_H
 #define DALI_TOOLKIT_IMAGE_ATLAS_H
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * 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.
@@ -157,7 +157,7 @@ public:
    * @param [in] size The width and height to fit the loaded image to.
    * @param [in] fittingMode The method used to fit the shape of the image before loading to the shape defined by the size parameter.
    * @param [in] orientationCorrection Reorient the image to respect any orientation metadata in its header.
-   * @param[in] atlasUploadObserver The observer to observe the upload state inside the ImageAtlas.
+   * @param [in] atlasUploadObserver The observer to observe the upload state inside the ImageAtlas.
    * @return True if there is enough space to fit this image in,false otherwise.
    * @note The valid callback function here is required to have the signature of void( void ).
    */
index 412eda7..ea10924 100644 (file)
@@ -21,6 +21,9 @@
 // EXTERNAL INCLUDES
 #include <dali/integration-api/adaptor-framework/adaptor.h>
 
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/visuals/visual-factory-impl.h>
+
 namespace Dali
 {
 namespace Toolkit
@@ -71,7 +74,24 @@ uint32_t AsyncImageLoader::Load(const VisualUrl&                         url,
     mLoadThread.Start();
     mIsLoadThreadStarted = true;
   }
-  mLoadThread.AddTask(new LoadingTask(++mLoadTaskId, url, dimensions, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad));
+  if(url.IsBufferResource())
+  {
+    auto visualFactory = Toolkit::VisualFactory::Get();
+    if(visualFactory)
+    {
+      // Get EncodedImageBuffer from texturemanager
+      // and make new LoadingTask with buffer
+      auto& textureManager = GetImplementation(visualFactory).GetTextureManager();
+
+      const EncodedImageBuffer& encodedBuffer = textureManager.GetEncodedImageBuffer(url.GetUrl());
+
+      mLoadThread.AddTask(new LoadingTask(++mLoadTaskId, encodedBuffer, dimensions, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad));
+    }
+  }
+  else
+  {
+    mLoadThread.AddTask(new LoadingTask(++mLoadTaskId, url, dimensions, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad));
+  }
 
   return mLoadTaskId;
 }
index 7fc344f..43b0707 100644 (file)
@@ -19,6 +19,7 @@
 #include "image-load-thread.h"
 
 // EXTERNAL INCLUDES
+#include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
 #include <dali/devel-api/adaptor-framework/image-loading.h>
 #include <dali/devel-api/adaptor-framework/thread-settings.h>
 #include <dali/integration-api/adaptor-framework/adaptor.h>
@@ -33,6 +34,7 @@ namespace Internal
 LoadingTask::LoadingTask(uint32_t id, Dali::AnimatedImageLoading animatedImageLoading, uint32_t frameIndex)
 : pixelBuffer(),
   url(),
+  encodedImageBuffer(),
   id(id),
   dimensions(),
   fittingMode(),
@@ -51,6 +53,26 @@ LoadingTask::LoadingTask(uint32_t id, Dali::AnimatedImageLoading animatedImageLo
 LoadingTask::LoadingTask(uint32_t id, const VisualUrl& url, ImageDimensions dimensions, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
 : pixelBuffer(),
   url(url),
+  encodedImageBuffer(),
+  id(id),
+  dimensions(dimensions),
+  fittingMode(fittingMode),
+  samplingMode(samplingMode),
+  orientationCorrection(orientationCorrection),
+  preMultiplyOnLoad(preMultiplyOnLoad),
+  isMaskTask(false),
+  maskPixelBuffer(),
+  contentScale(1.0f),
+  cropToMask(false),
+  animatedImageLoading(),
+  frameIndex(0u)
+{
+}
+
+LoadingTask::LoadingTask(uint32_t id, const EncodedImageBuffer& encodedImageBuffer, ImageDimensions dimensions, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
+: pixelBuffer(),
+  url(),
+  encodedImageBuffer(encodedImageBuffer),
   id(id),
   dimensions(dimensions),
   fittingMode(fittingMode),
@@ -69,6 +91,7 @@ LoadingTask::LoadingTask(uint32_t id, const VisualUrl& url, ImageDimensions dime
 LoadingTask::LoadingTask(uint32_t id, Devel::PixelBuffer pixelBuffer, Devel::PixelBuffer maskPixelBuffer, float contentScale, bool cropToMask, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
 : pixelBuffer(pixelBuffer),
   url(""),
+  encodedImageBuffer(),
   id(id),
   dimensions(),
   fittingMode(),
@@ -90,11 +113,15 @@ void LoadingTask::Load()
   {
     pixelBuffer = animatedImageLoading.LoadFrame(frameIndex);
   }
-  else if(url.IsLocalResource())
+  else if(encodedImageBuffer)
+  {
+    pixelBuffer = Dali::LoadImageFromBuffer(encodedImageBuffer.GetRawBuffer(), dimensions, fittingMode, samplingMode, orientationCorrection);
+  }
+  else if(url.IsValid() && url.IsLocalResource())
   {
     pixelBuffer = Dali::LoadImageFromFile(url.GetUrl(), dimensions, fittingMode, samplingMode, orientationCorrection);
   }
-  else
+  else if(url.IsValid())
   {
     pixelBuffer = Dali::DownloadImageSynchronously(url.GetUrl(), dimensions, fittingMode, samplingMode, orientationCorrection);
   }
index 9505b17..95ec260 100644 (file)
@@ -29,6 +29,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/public-api/adaptor-framework/encoded-image-buffer.h>
 
 namespace Dali
 {
@@ -72,6 +73,24 @@ struct LoadingTask
   /**
    * Constructor.
    * @param [in] id of the task
+   * @param [in] encodedImageBuffer The encoded buffer of the image to load.
+   * @param [in] size The width and height to fit the loaded image to, 0.0 means whole image
+   * @param [in] fittingMode The method used to fit the shape of the image before loading to the shape defined by the size parameter.
+   * @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.
+   */
+  LoadingTask(uint32_t                                 id,
+              const EncodedImageBuffer&                encodedImageBuffer,
+              ImageDimensions                          dimensions,
+              FittingMode::Type                        fittingMode,
+              SamplingMode::Type                       samplingMode,
+              bool                                     orientationCorrection,
+              DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad);
+
+  /**
+   * Constructor.
+   * @param [in] id of the task
    * @param [in] pixelBuffer of the to be masked image
    * @param [in] maskPixelBuffer of the mask image
    * @param [in] contentScale The factor to scale the content
@@ -111,6 +130,7 @@ public:
   Devel::PixelBuffer pixelBuffer;                                     ///< 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.
   ImageDimensions                          dimensions;                ///< dimensions to load
   FittingMode::Type                        fittingMode;               ///< fitting options
index 055738f..52ba6c4 100644 (file)
  */
 
 // CLASS HEADER
-#include <dali-toolkit/devel-api/image-loader/texture-manager.h>
 #include <dali-toolkit/internal/image-loader/image-url-impl.h>
 
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/image-loader/texture-manager.h>
+#include <dali-toolkit/internal/visuals/visual-factory-impl.h>
+#include <dali-toolkit/internal/visuals/texture-manager-impl.h>
+#include <dali-toolkit/internal/visuals/visual-url.h>
+
 namespace Dali
 {
 namespace Toolkit
@@ -26,14 +31,39 @@ namespace Toolkit
 namespace Internal
 {
 ImageUrl::ImageUrl(Texture& texture)
-: mUrl("")
 {
   mUrl = Dali::Toolkit::TextureManager::AddTexture(texture);
 }
 
+ImageUrl::ImageUrl(const EncodedImageBuffer& encodedImageBuffer)
+: mUrl("")
+{
+  auto visualFactory = Dali::Toolkit::VisualFactory::Get();
+  if(visualFactory)
+  {
+    auto& textureManager = GetImplementation(visualFactory).GetTextureManager();
+    mUrl = textureManager.AddExternalEncodedImageBuffer(encodedImageBuffer);
+  }
+}
+
 ImageUrl::~ImageUrl()
 {
-  Dali::Toolkit::TextureManager::RemoveTexture(mUrl);
+  if(mUrl.size() > 0)
+  {
+    auto visualFactory = Dali::Toolkit::VisualFactory::Get();
+    if(visualFactory)
+    {
+      auto& textureManager = GetImplementation(visualFactory).GetTextureManager();
+      if(VisualUrl::TEXTURE == VisualUrl::GetProtocolType(mUrl))
+      {
+        textureManager.RemoveExternalTexture(mUrl);
+      }
+      else if(VisualUrl::BUFFER == VisualUrl::GetProtocolType(mUrl))
+      {
+        textureManager.RemoveExternalEncodedImageBuffer(mUrl);
+      }
+    }
+  }
 }
 
 ImageUrlPtr ImageUrl::New(Texture& texture)
@@ -42,6 +72,12 @@ ImageUrlPtr ImageUrl::New(Texture& texture)
   return imageUrlPtr;
 }
 
+ImageUrlPtr ImageUrl::New(const EncodedImageBuffer& encodedImageBuffer)
+{
+  ImageUrlPtr imageUrlPtr = new ImageUrl(encodedImageBuffer);
+  return imageUrlPtr;
+}
+
 const std::string& ImageUrl::GetUrl() const
 {
   return mUrl;
index 45981b2..99616bf 100644 (file)
@@ -20,6 +20,7 @@
 
 // EXTERNAL INCLUDES
 #include <dali/public-api/object/base-object.h>
+#include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
 #include <string>
 
 // INTERNAL INCLUDES
@@ -43,11 +44,21 @@ public:
   ImageUrl(Texture& texture);
 
   /**
+   * @brief Constructor.
+   */
+  ImageUrl(const EncodedImageBuffer& encodedImageBuffer);
+
+  /**
    * @copydoc Dali::Toolkit::ImageUrl::New
    */
   static ImageUrlPtr New(Texture& texture);
 
   /**
+   * @copydoc Dali::Toolkit::ImageUrl::New
+   */
+  static ImageUrlPtr New(const EncodedImageBuffer& encodedImageBuffer);
+
+  /**
    * @copydoc Dali::Toolkit::ImageUrl::GetUrl
    */
   const std::string& GetUrl() const;
index bbbab23..16a4a4a 100644 (file)
@@ -595,7 +595,7 @@ void ImageVisual::LoadTexture(bool& atlasing, Vector4& atlasRect, TextureSet& te
 
 bool ImageVisual::AttemptAtlasing()
 {
-  return (!mImpl->mCustomShader && mImageUrl.GetProtocolType() == VisualUrl::LOCAL && mAttemptAtlasing);
+  return (!mImpl->mCustomShader && (mImageUrl.IsLocalResource() || mImageUrl.IsBufferResource()) && mAttemptAtlasing);
 }
 
 void ImageVisual::InitializeRenderer()
index 6ef02cc..d9c26aa 100644 (file)
@@ -153,7 +153,7 @@ void NPatchVisual::LoadImages()
   TextureManager& textureManager     = mFactoryCache.GetTextureManager();
   bool            synchronousLoading = mImpl->mFlags & Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
 
-  if(mId == NPatchData::INVALID_NPATCH_DATA_ID && mImageUrl.IsLocalResource())
+  if(mId == NPatchData::INVALID_NPATCH_DATA_ID && (mImageUrl.IsLocalResource() || mImageUrl.IsBufferResource()))
   {
     bool preMultiplyOnLoad = IsPreMultipliedAlphaEnabled() && !mImpl->mCustomShader ? true : false;
     mId                    = mLoader.Load(textureManager, this, mImageUrl, mBorder, preMultiplyOnLoad, synchronousLoading);
@@ -165,7 +165,7 @@ void NPatchVisual::LoadImages()
     }
   }
 
-  if(!mAuxiliaryPixelBuffer && mAuxiliaryUrl.IsValid() && mAuxiliaryUrl.IsLocalResource())
+  if(!mAuxiliaryPixelBuffer && mAuxiliaryUrl.IsValid() && (mAuxiliaryUrl.IsLocalResource() || mAuxiliaryUrl.IsBufferResource()))
   {
     // Load the auxiliary image
     auto preMultiplyOnLoading = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
index 7ca271f..dbb1230 100644 (file)
@@ -200,7 +200,18 @@ Devel::PixelBuffer TextureManager::LoadPixelBuffer(
   {
     if(url.IsValid())
     {
-      pixelBuffer = LoadImageFromFile(url.GetUrl(), desiredSize, fittingMode, samplingMode, orientationCorrection);
+      if(url.IsBufferResource())
+      {
+        const EncodedImageBuffer& encodedImageBuffer = GetEncodedImageBuffer(url.GetUrl());
+        if(encodedImageBuffer)
+        {
+          pixelBuffer = LoadImageFromBuffer(encodedImageBuffer.GetRawBuffer(), desiredSize, fittingMode, samplingMode, orientationCorrection);
+        }
+      }
+      else
+      {
+        pixelBuffer = LoadImageFromFile(url.GetUrl(), desiredSize, fittingMode, samplingMode, orientationCorrection);
+      }
       if(pixelBuffer && preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD)
       {
         PreMultiply(pixelBuffer, preMultiplyOnLoad);
@@ -245,7 +256,19 @@ TextureSet TextureManager::LoadTexture(
     PixelData data;
     if(url.IsValid())
     {
-      Devel::PixelBuffer pixelBuffer = LoadImageFromFile(url.GetUrl(), desiredSize, fittingMode, samplingMode, orientationCorrection);
+      Devel::PixelBuffer pixelBuffer;
+      if(url.IsBufferResource())
+      {
+        const EncodedImageBuffer& encodedImageBuffer = GetEncodedImageBuffer(url.GetUrl());
+        if(encodedImageBuffer)
+        {
+          pixelBuffer = LoadImageFromBuffer(encodedImageBuffer.GetRawBuffer(), desiredSize, fittingMode, samplingMode, orientationCorrection);
+        }
+      }
+      else
+      {
+        pixelBuffer = LoadImageFromFile(url.GetUrl(), desiredSize, fittingMode, samplingMode, orientationCorrection);
+      }
       if(maskInfo && maskInfo->mAlphaMaskUrl.IsValid())
       {
         Devel::PixelBuffer maskPixelBuffer = LoadImageFromFile(maskInfo->mAlphaMaskUrl.GetUrl(), ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, true);
@@ -434,12 +457,35 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
     DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureManager::RequestLoad( url=%s observer=%p ) Using cached texture id@%d, textureId=%d\n", url.GetUrl().c_str(), observer, cacheIndex, textureId);
   }
 
+  // Check if the requested Texture exist in Encoded Buffer
+  // This mean, that buffer is not cached, and need to be decoded.
+  if(textureId == INVALID_TEXTURE_ID && VisualUrl::BUFFER == url.GetProtocolType())
+  {
+    std::string location = url.GetLocation();
+    if(location.size() > 0u)
+    {
+      TextureId                 targetId           = std::stoi(location);
+      const EncodedImageBuffer& encodedImageBuffer = GetEncodedImageBuffer(targetId);
+      if(encodedImageBuffer)
+      {
+        textureId = targetId;
+        // Insert this buffer at mTextureInfoContainer.
+        // This buffer will decode at ImageLoaderThread.
+        bool preMultiply = (preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD);
+        mTextureInfoContainer.push_back(TextureInfo(textureId, maskTextureId, url, desiredSize, contentScale, fittingMode, samplingMode, false, cropToMask, useAtlas, textureHash, orientationCorrection, preMultiply, animatedImageLoading, frameIndex));
+        cacheIndex = mTextureInfoContainer.size() - 1u;
+
+        DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureManager::RequestLoad( url=%s observer=%p ) New buffered texture, cacheIndex:%d, textureId=%d\n", url.GetUrl().c_str(), observer, cacheIndex, textureId);
+      }
+    }
+  }
+
   if(textureId == INVALID_TEXTURE_ID) // There was no caching, or caching not required
   {
     // We need a new Texture.
     textureId        = GenerateUniqueTextureId();
     bool preMultiply = (preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD);
-    mTextureInfoContainer.push_back(TextureInfo(textureId, maskTextureId, url.GetUrl(), desiredSize, contentScale, fittingMode, samplingMode, false, cropToMask, useAtlas, textureHash, orientationCorrection, preMultiply, animatedImageLoading, frameIndex));
+    mTextureInfoContainer.push_back(TextureInfo(textureId, maskTextureId, url, desiredSize, contentScale, fittingMode, samplingMode, false, cropToMask, useAtlas, textureHash, orientationCorrection, preMultiply, animatedImageLoading, frameIndex));
     cacheIndex = mTextureInfoContainer.size() - 1u;
 
     DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureManager::RequestLoad( url=%s observer=%p ) New texture, cacheIndex:%d, textureId=%d\n", url.GetUrl().c_str(), observer, cacheIndex, textureId);
@@ -656,6 +702,35 @@ TextureSet TextureManager::GetTextureSet(TextureId textureId)
   return textureSet;
 }
 
+EncodedImageBuffer TextureManager::GetEncodedImageBuffer(TextureId textureId)
+{
+  EncodedImageBuffer encodedImageBuffer; // empty handle
+  for(auto&& elem : mEncodedBufferTextures)
+  {
+    if(elem.textureId == textureId)
+    {
+      encodedImageBuffer = elem.encodedImageBuffer;
+      break;
+    }
+  }
+  return encodedImageBuffer;
+}
+
+EncodedImageBuffer TextureManager::GetEncodedImageBuffer(const std::string& url)
+{
+  EncodedImageBuffer encodedImageBuffer; // empty handle
+  if(url.size() > 0 && VisualUrl::BUFFER == VisualUrl::GetProtocolType(url))
+  {
+    std::string location = VisualUrl::GetLocation(url);
+    if(location.size() > 0u)
+    {
+      TextureId targetId = std::stoi(location);
+      return GetEncodedImageBuffer(targetId);
+    }
+  }
+  return encodedImageBuffer;
+}
+
 std::string TextureManager::AddExternalTexture(TextureSet& textureSet)
 {
   TextureManager::ExternalTextureInfo info;
@@ -666,13 +741,30 @@ std::string TextureManager::AddExternalTexture(TextureSet& textureSet)
   return VisualUrl::CreateTextureUrl(std::to_string(info.textureId));
 }
 
+std::string TextureManager::AddExternalEncodedImageBuffer(const EncodedImageBuffer& encodedImageBuffer)
+{
+  // Duplication check
+  for(auto&& elem : mEncodedBufferTextures)
+  {
+    if(elem.encodedImageBuffer == encodedImageBuffer)
+    {
+      // If same buffer added, increase reference count and return.
+      elem.referenceCount++;
+      return VisualUrl::CreateBufferUrl(std::to_string(elem.textureId));;
+    }
+  }
+  TextureManager::EncodedBufferTextureInfo info(GenerateUniqueTextureId(), encodedImageBuffer);
+  mEncodedBufferTextures.emplace_back(info);
+  return VisualUrl::CreateBufferUrl(std::to_string(info.textureId));
+}
+
 TextureSet TextureManager::RemoveExternalTexture(const std::string& url)
 {
   if(url.size() > 0u)
   {
-    // get the location from the Url
     if(VisualUrl::TEXTURE == VisualUrl::GetProtocolType(url))
     {
+      // get the location from the Url
       std::string location = VisualUrl::GetLocation(url);
       if(location.size() > 0u)
       {
@@ -696,7 +788,37 @@ TextureSet TextureManager::RemoveExternalTexture(const std::string& url)
   return TextureSet();
 }
 
-void TextureManager::UseExternalTexture(const VisualUrl& url)
+EncodedImageBuffer TextureManager::RemoveExternalEncodedImageBuffer(const std::string& url)
+{
+  if(url.size() > 0u)
+  {
+    if(VisualUrl::BUFFER == VisualUrl::GetProtocolType(url))
+    {
+      // get the location from the Url
+      std::string location = VisualUrl::GetLocation(url);
+      if(location.size() > 0u)
+      {
+        TextureId id = std::stoi(location);
+        const auto end = mEncodedBufferTextures.end();
+        for(auto iter = mEncodedBufferTextures.begin(); iter != end; ++iter)
+        {
+          if(iter->textureId == id)
+          {
+            auto encodedImageBuffer = iter->encodedImageBuffer;
+            if(--(iter->referenceCount) <= 0)
+            {
+              mEncodedBufferTextures.erase(iter);
+            }
+            return encodedImageBuffer;
+          }
+        }
+      }
+    }
+  }
+  return EncodedImageBuffer();
+}
+
+void TextureManager::UseExternalResource(const VisualUrl& url)
 {
   if(VisualUrl::TEXTURE == url.GetProtocolType())
   {
@@ -714,6 +836,22 @@ void TextureManager::UseExternalTexture(const VisualUrl& url)
       }
     }
   }
+  else if(VisualUrl::BUFFER == url.GetProtocolType())
+  {
+    std::string location = url.GetLocation();
+    if(location.size() > 0u)
+    {
+      TextureId id = std::stoi(location);
+      for(auto&& elem : mEncodedBufferTextures)
+      {
+        if(elem.textureId == id)
+        {
+          elem.referenceCount++;
+          return;
+        }
+      }
+    }
+  }
 }
 
 void TextureManager::AddObserver(TextureManager::LifecycleObserver& observer)
@@ -797,7 +935,7 @@ void TextureManager::LoadTexture(TextureInfo& textureInfo, TextureUploadObserver
   textureInfo.loadState = LoadState::LOADING;
   if(!textureInfo.loadSynchronously)
   {
-    auto& loadersContainer  = textureInfo.url.IsLocalResource() ? mAsyncLocalLoaders : mAsyncRemoteLoaders;
+    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());
@@ -996,7 +1134,7 @@ void TextureManager::ApplyMask(TextureInfo& textureInfo, TextureId maskTextureId
     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() ? mAsyncLocalLoaders : mAsyncRemoteLoaders;
+    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());
index c9618a9..48eea78 100644 (file)
@@ -20,6 +20,7 @@
 // EXTERNAL INCLUDES
 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
 #include <dali/devel-api/common/owner-container.h>
+#include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
 #include <dali/public-api/common/dali-vector.h>
 #include <dali/public-api/object/ref-object.h>
 #include <dali/public-api/rendering/geometry.h>
@@ -389,6 +390,20 @@ public:
   TextureSet GetTextureSet(TextureId textureId);
 
   /**
+   * @brief Get the encoded image buffer
+   * @param[in] textureId The textureId to look up
+   * @return the encoded image buffer, or an empty handle if textureId is not valid
+   */
+  EncodedImageBuffer GetEncodedImageBuffer(TextureId textureId);
+
+  /**
+   * @brief Get the encoded image buffer by VisualUrl
+   * @param[in] url The url to look up
+   * @return the encoded image buffer, or an empty handle if url is not buffer resource or buffer is not valid
+   */
+  EncodedImageBuffer GetEncodedImageBuffer(const std::string& url);
+
+  /**
    * Adds an external texture to the texture manager
    * @param[in] texture The texture to add
    * @return string containing the URL for the texture
@@ -396,6 +411,13 @@ public:
   std::string AddExternalTexture(TextureSet& texture);
 
   /**
+   * Adds an external encoded image buffer to the texture manager
+   * @param[in] encodedImageBuffer The image buffer to add
+   * @return string containing the URL for the texture
+   */
+  std::string AddExternalEncodedImageBuffer(const EncodedImageBuffer& encodedImageBuffer);
+
+  /**
    * Removes an external texture from texture manager
    * @param[in] url The string containing the texture to remove
    * @return handle to the texture
@@ -403,10 +425,17 @@ public:
   TextureSet RemoveExternalTexture(const std::string& url);
 
   /**
-   * @brief Notify that external textures are used.
+   * Removes an external encoded image buffer from texture manager
+   * @param[in] url The string containing the encoded image buffer to remove
+   * @return handle to the encoded image buffer
+   */
+  EncodedImageBuffer RemoveExternalEncodedImageBuffer(const std::string& url);
+
+  /**
+   * @brief Notify that external textures or external encoded image buffers are used.
    * @param[in] url The URL of the texture to use.
    */
-  void UseExternalTexture(const VisualUrl& url);
+  void UseExternalResource(const VisualUrl& url);
 
   /**
    * Add an observer to the object.
@@ -859,6 +888,20 @@ private:
     int16_t    referenceCount{1};
   };
 
+  struct EncodedBufferTextureInfo
+  {
+    EncodedBufferTextureInfo(TextureId                 textureId,
+                             const EncodedImageBuffer& encodedImageBuffer)
+    : textureId(textureId),
+      encodedImageBuffer(encodedImageBuffer),
+      referenceCount(1u)
+    {
+    }
+    TextureId          textureId;
+    EncodedImageBuffer encodedImageBuffer;
+    int16_t            referenceCount;
+  };
+
 private:
   /**
    * Deleted copy constructor.
@@ -877,15 +920,16 @@ private:
    */
   void ObserverDestroyed(TextureUploadObserver* observer);
 
-private:                                                             // Member Variables:
-  TextureInfoContainerType                    mTextureInfoContainer; ///< Used to manage the life-cycle and caching of Textures
-  RoundRobinContainerView<AsyncLoadingHelper> mAsyncLocalLoaders;    ///< The Asynchronous image loaders used to provide all local async loads
-  RoundRobinContainerView<AsyncLoadingHelper> mAsyncRemoteLoaders;   ///< The Asynchronous image loaders used to provide all remote async loads
-  std::vector<ExternalTextureInfo>            mExternalTextures;     ///< Externally provided textures
-  Dali::Vector<LifecycleObserver*>            mLifecycleObservers;   ///< Lifecycle observers of texture manager
-  Dali::Vector<LoadQueueElement>              mLoadQueue;            ///< Queue of textures to load after NotifyObservers
-  TextureId                                   mCurrentTextureId;     ///< The current value used for the unique Texture Id generation
-  bool                                        mQueueLoadFlag;        ///< Flag that causes Load Textures to be queued.
+private:                                                              // Member Variables:
+  TextureInfoContainerType                    mTextureInfoContainer;  ///< Used to manage the life-cycle and caching of Textures
+  RoundRobinContainerView<AsyncLoadingHelper> mAsyncLocalLoaders;     ///< The Asynchronous image loaders used to provide all local async loads
+  RoundRobinContainerView<AsyncLoadingHelper> mAsyncRemoteLoaders;    ///< The Asynchronous image loaders used to provide all remote async loads
+  std::vector<ExternalTextureInfo>            mExternalTextures;      ///< Externally provided textures
+  std::vector<EncodedBufferTextureInfo>       mEncodedBufferTextures; ///< Externally encoded buffer textures
+  Dali::Vector<LifecycleObserver*>            mLifecycleObservers;    ///< Lifecycle observers of texture manager
+  Dali::Vector<LoadQueueElement>              mLoadQueue;             ///< Queue of textures to load after NotifyObservers
+  TextureId                                   mCurrentTextureId;      ///< The current value used for the unique Texture Id generation
+  bool                                        mQueueLoadFlag;         ///< Flag that causes Load Textures to be queued.
 };
 
 } // namespace Internal
index 1979f78..70c6dc2 100644 (file)
@@ -38,15 +38,28 @@ VisualUrl::ProtocolType ResolveLocation(const std::string& url)
   const uint32_t length  = url.size();
   if((length > 7) && urlCStr[5] == ':' && urlCStr[6] == '/' && urlCStr[7] == '/')
   {
-    // https://
-    if(('h' == tolower(urlCStr[0])) &&
-       ('t' == tolower(urlCStr[1])) &&
-       ('t' == tolower(urlCStr[2])) &&
-       ('p' == tolower(urlCStr[3])) &&
-       ('s' == tolower(urlCStr[4])))
+    // https:// or enbuf://
+    const char hOre = tolower(urlCStr[0]);
+    const char tOrn = tolower(urlCStr[1]);
+    const char tOrb = tolower(urlCStr[2]);
+    const char pOru = tolower(urlCStr[3]);
+    const char sOrf = tolower(urlCStr[4]);
+    if(('h' == hOre) &&
+       ('t' == tOrn) &&
+       ('t' == tOrb) &&
+       ('p' == pOru) &&
+       ('s' == sOrf))
     {
       return VisualUrl::REMOTE;
     }
+    if(('e' == hOre) &&
+       ('n' == tOrn) &&
+       ('b' == tOrb) &&
+       ('u' == pOru) &&
+       ('f' == sOrf))
+    {
+      return VisualUrl::BUFFER;
+    }
   }
   else if((length > 6) && urlCStr[4] == ':' && urlCStr[5] == '/' && urlCStr[6] == '/')
   {
@@ -73,18 +86,20 @@ VisualUrl::ProtocolType ResolveLocation(const std::string& url)
   else if((length > 5) && urlCStr[3] == ':' && urlCStr[4] == '/' && urlCStr[5] == '/')
   {
     // ftp:// or ssh://
-    const char fOrS = tolower(urlCStr[0]);
-    if(('f' == fOrS) || ('s' == fOrS))
+    const char fOrs = tolower(urlCStr[0]);
+    const char tOrs = tolower(urlCStr[1]);
+    const char pOrh = tolower(urlCStr[2]);
+    if(('f' == fOrs) &&
+       ('t' == tOrs) &&
+       ('p' == pOrh))
     {
-      const char tOrs = tolower(urlCStr[1]);
-      if(('t' == tOrs) || ('s' == tOrs))
-      {
-        const char pOrh = tolower(urlCStr[2]);
-        if(('p' == pOrh) || ('h' == pOrh))
-        {
-          return VisualUrl::REMOTE;
-        }
-      }
+      return VisualUrl::REMOTE;
+    }
+    if(('s' == fOrs) &&
+       ('s' == tOrs) &&
+       ('h' == pOrh))
+    {
+      return VisualUrl::REMOTE;
     }
   }
   return VisualUrl::LOCAL;
@@ -208,9 +223,9 @@ VisualUrl::VisualUrl(const std::string& url)
   if(!url.empty())
   {
     mLocation = ResolveLocation(url);
-    if(VisualUrl::TEXTURE != mLocation)
+    if(VisualUrl::TEXTURE != mLocation && VisualUrl::BUFFER != mLocation)
     {
-      // TEXTURE location url doesn't need type resolving, REGULAR_IMAGE is fine
+      // TEXTURE and BUFFER location url doesn't need type resolving, REGULAR_IMAGE is fine
       mType = ResolveType(url);
     }
     else
@@ -218,7 +233,7 @@ VisualUrl::VisualUrl(const std::string& url)
       Toolkit::VisualFactory factory = Toolkit::VisualFactory::Get();
       if(factory)
       {
-        GetImplementation(factory).GetTextureManager().UseExternalTexture(*this);
+        GetImplementation(factory).GetTextureManager().UseExternalResource(*this);
       }
     }
   }
@@ -229,12 +244,12 @@ VisualUrl::VisualUrl(const VisualUrl& url)
   mType(url.mType),
   mLocation(url.mLocation)
 {
-  if(VisualUrl::TEXTURE == mLocation)
+  if(VisualUrl::TEXTURE == mLocation || VisualUrl::BUFFER == mLocation)
   {
     Toolkit::VisualFactory factory = Toolkit::VisualFactory::Get();
     if(factory)
     {
-      GetImplementation(factory).GetTextureManager().UseExternalTexture(*this);
+      GetImplementation(factory).GetTextureManager().UseExternalResource(*this);
     }
   }
 }
@@ -249,6 +264,14 @@ VisualUrl::~VisualUrl()
       GetImplementation(factory).GetTextureManager().RemoveExternalTexture(mUrl);
     }
   }
+  else if(VisualUrl::BUFFER == mLocation)
+  {
+    Toolkit::VisualFactory factory = Toolkit::VisualFactory::Get();
+    if(factory)
+    {
+      GetImplementation(factory).GetTextureManager().RemoveExternalEncodedImageBuffer(mUrl);
+    }
+  }
 }
 
 VisualUrl& VisualUrl::operator=(const VisualUrl& url)
@@ -263,17 +286,25 @@ VisualUrl& VisualUrl::operator=(const VisualUrl& url)
         GetImplementation(factory).GetTextureManager().RemoveExternalTexture(mUrl);
       }
     }
+    else if(VisualUrl::BUFFER == mLocation)
+    {
+      Toolkit::VisualFactory factory = Toolkit::VisualFactory::Get();
+      if(factory)
+      {
+        GetImplementation(factory).GetTextureManager().RemoveExternalEncodedImageBuffer(mUrl);
+      }
+    }
 
     mUrl      = url.mUrl;
     mType     = url.mType;
     mLocation = url.mLocation;
 
-    if(VisualUrl::TEXTURE == mLocation)
+    if(VisualUrl::TEXTURE == mLocation || VisualUrl::BUFFER == mLocation)
     {
       Toolkit::VisualFactory factory = Toolkit::VisualFactory::Get();
       if(factory)
       {
-        GetImplementation(factory).GetTextureManager().UseExternalTexture(*this);
+        GetImplementation(factory).GetTextureManager().UseExternalResource(*this);
       }
     }
   }
@@ -305,6 +336,11 @@ bool VisualUrl::IsLocalResource() const
   return mLocation == VisualUrl::LOCAL;
 }
 
+bool VisualUrl::IsBufferResource() const
+{
+  return mLocation == VisualUrl::BUFFER;
+}
+
 std::string VisualUrl::GetLocation() const
 {
   return GetLocation(mUrl);
@@ -315,6 +351,11 @@ std::string VisualUrl::CreateTextureUrl(const std::string& location)
   return "dali://" + location;
 }
 
+std::string VisualUrl::CreateBufferUrl(const std::string& location)
+{
+  return "enbuf://" + location;
+}
+
 VisualUrl::ProtocolType VisualUrl::GetProtocolType(const std::string& url)
 {
   return ResolveLocation(url);
@@ -330,7 +371,6 @@ std::string VisualUrl::GetLocation(const std::string& url)
   return url;
 }
 
-
 } // namespace Internal
 
 } // namespace Toolkit
index a772bd1..555e383 100644 (file)
@@ -45,7 +45,8 @@ public:
   {
     LOCAL,   ///< file in local file system
     TEXTURE, ///< texture uploaded to texture manager
-    REMOTE   ///< remote image
+    REMOTE,  ///< remote image
+    BUFFER   ///< encoded image buffer
   };
 
   /**
@@ -111,6 +112,11 @@ public:
   bool IsLocalResource() const;
 
   /**
+   * @return true if the location is BUFFER, i.e. may contain EncodedImageBuffer
+   */
+  bool IsBufferResource() const;
+
+  /**
    * @return the location part of the url
    */
   std::string GetLocation() const;
@@ -123,6 +129,13 @@ public:
   static std::string CreateTextureUrl(const std::string& location);
 
   /**
+   * Helper to create a URL of type BUFFER
+   * @param location the location of the texture
+   * @return the Url
+   */
+  static std::string CreateBufferUrl(const std::string& location);
+
+  /**
    * Helper to get a ProtocolType from url
    * @param url the url of the texture
    * @return the protocol type
@@ -135,6 +148,7 @@ public:
    * @return the location
    */
   static std::string GetLocation(const std::string& url);
+
 private:
   std::string  mUrl;
   Type         mType;
index 65b9601..f936fdc 100644 (file)
@@ -38,6 +38,12 @@ ImageUrl ImageUrl::New(Texture& texture)
   return ImageUrl(internal.Get());
 }
 
+ImageUrl ImageUrl::New(const EncodedImageBuffer& encodedImageBuffer)
+{
+  Toolkit::Internal::ImageUrlPtr internal = Toolkit::Internal::ImageUrl::New(encodedImageBuffer);
+  return ImageUrl(internal.Get());
+}
+
 ImageUrl ImageUrl::DownCast(BaseHandle handle)
 {
   return ImageUrl(dynamic_cast<Toolkit::Internal::ImageUrl*>(handle.GetObjectPtr()));
index 819198b..976f179 100644 (file)
@@ -20,6 +20,7 @@
 // EXTERNAL INCLUDES
 #include <string>
 #include <dali/public-api/rendering/texture.h>
+#include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/dali-toolkit-common.h>
@@ -39,6 +40,7 @@ class ImageUrl;
  * Application can get url from ImageUrl.
  * When application does not use this anymore, the destructor of the ImageUrl is called.
  * At this time, the buffer is deleted from the texture manager.
+ * @note Visual also have reference of the buffer. In this case, buffer will be deleted after visual is deleted.
  */
 class DALI_TOOLKIT_API ImageUrl : public BaseHandle
 {
@@ -63,6 +65,14 @@ public:
   static ImageUrl New(Texture& texture);
 
   /**
+   * @brief Create an initialized ImageUrl.
+   *
+   * @param[in] encodedImageBuffer The encoded image buffer url is got from external buffer.
+   * @return A handle to a newly allocated Dali resource.
+   */
+  static ImageUrl New(const EncodedImageBuffer& encodedImageBuffer);
+
+  /**
    * @brief Downcast an Object handle to ImageUrl handle.
    *
    * If handle points to a ImageUrl object the downcast produces valid
index b44061e..7b91059 100644 (file)
@@ -60,6 +60,11 @@ Dali::Toolkit::ImageUrl GenerateUrl(const Dali::NativeImageSourcePtr nativeImage
   return imageUrl;
 }
 
+Dali::Toolkit::ImageUrl GenerateUrl(const Dali::EncodedImageBuffer encodedImageBuffer)
+{
+  return Dali::Toolkit::ImageUrl::New(encodedImageBuffer);
+}
+
 } // namespace Image
 
 } // namespace Toolkit
index ad2f56e..6db6e7e 100644 (file)
@@ -19,6 +19,7 @@
 
 // EXTERNAL INCLUDES
 #include <dali/public-api/adaptor-framework/native-image-source.h>
+#include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
 #include <dali/public-api/images/pixel-data.h>
 #include <dali/public-api/rendering/frame-buffer.h>
 
@@ -78,6 +79,15 @@ DALI_TOOLKIT_API Dali::Toolkit::ImageUrl GenerateUrl(const Dali::PixelData pixel
  */
 DALI_TOOLKIT_API Dali::Toolkit::ImageUrl GenerateUrl(const Dali::NativeImageSourcePtr nativeImageSource);
 
+/**
+ * @brief Generate a Url from encoded image buffer.
+ * This Url can be used in visuals to render the image.
+ * @note This method does not check for duplicates, If same encoded image buffer is entered multiple times, a different URL is returned each time.
+ * @param[in] encodedImageBuffer the encoded image buffer to converted to Url
+ * @return the ImageUrl representing this encoded image buffer
+ */
+DALI_TOOLKIT_API Dali::Toolkit::ImageUrl GenerateUrl(const Dali::EncodedImageBuffer encodedImageBuffer);
+
 } // namespace Image
 
 } // namespace Toolkit