[dali_1.3.0] Merge branch 'devel/master' 13/160713/1
authoradam.b <adam.b@samsung.com>
Fri, 17 Nov 2017 14:46:47 +0000 (14:46 +0000)
committeradam.b <adam.b@samsung.com>
Fri, 17 Nov 2017 14:46:47 +0000 (14:46 +0000)
Change-Id: Iad74ce47e665be00c02744b6de458b2ede8cef8c

automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp
automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp
dali-toolkit/internal/controls/control/control-data-impl.cpp
dali-toolkit/internal/visuals/image/image-visual.cpp
dali-toolkit/public-api/controls/control.h
dali-toolkit/public-api/controls/image-view/image-view.h
dali-toolkit/public-api/dali-toolkit-version.cpp
packaging/dali-toolkit.spec

index c8cf88f..a770a77 100644 (file)
@@ -25,6 +25,7 @@
 #include <dali-toolkit/devel-api/controls/control-devel.h>
 #include <dali-toolkit/devel-api/image-loader/texture-manager.h>
 #include <dali-toolkit/devel-api/visual-factory/visual-base.h>
+#include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
 
 #include <test-native-image.h>
 #include <sstream>
@@ -1507,3 +1508,108 @@ int UtcDaliImageViewReplaceImageAndGetNaturalSize(void)
 
   END_TEST;
 }
+
+int UtcDaliImageViewResourceReadySignalWithImmediateLoad(void)
+{
+  tet_infoline("Test Setting Image with IMMEDIATE load and receving ResourceReadySignal before staged.");
+
+  ToolkitTestApplication application;
+
+  gResourceReadySignalFired = false;
+
+  Property::Map imageMap;
+
+  imageMap[ ImageVisual::Property::URL ] = gImage_34_RGBA;
+  imageMap[ DevelImageVisual::Property::LOAD_POLICY ] =  DevelImageVisual::LoadPolicy::IMMEDIATE;
+
+  tet_infoline("Creating ImageView without URL so image does not start loading");
+  ImageView imageView = ImageView::New();
+  tet_infoline("Connect to image loaded signal before setting image");
+  imageView.ResourceReadySignal().Connect( &ResourceReadySignal);
+  tet_infoline("Setting Image with IMMEDIATE load, signal already connected so will be triggered.");
+  imageView.SetProperty( ImageView::Property::IMAGE, imageMap );
+
+  // loading started, this waits for the loader thread
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(16);
+
+  DALI_TEST_EQUALS( gResourceReadySignalFired, true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliImageViewResourceReadySignalWithReusedImage(void)
+{
+  tet_infoline("Test Setting Image that was already loaded by another ImageView and still getting ResourceReadySignal.");
+
+  ToolkitTestApplication application;
+
+  gResourceReadySignalFired = false;
+
+  Property::Map imageMap;
+
+  imageMap[ ImageVisual::Property::URL ] = gImage_34_RGBA;
+  imageMap[ DevelImageVisual::Property::LOAD_POLICY ] =  DevelImageVisual::LoadPolicy::IMMEDIATE;
+
+  ImageView imageView = ImageView::New();
+  imageView.ResourceReadySignal().Connect( &ResourceReadySignal);
+  imageView.SetProperty( ImageView::Property::IMAGE, imageMap );
+
+  // loading started, this waits for the loader thread
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(16);
+
+  DALI_TEST_EQUALS( gResourceReadySignalFired, true, TEST_LOCATION );
+  gResourceReadySignalFired = false;
+
+  ImageView imageViewWithExistingImage = ImageView::New();
+  imageViewWithExistingImage.ResourceReadySignal().Connect( &ResourceReadySignal);
+  imageViewWithExistingImage.SetProperty( ImageView::Property::IMAGE, imageMap );
+
+  DALI_TEST_EQUALS( gResourceReadySignalFired, true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliImageViewResourceReadySignalWithReusedImage02(void)
+{
+  tet_infoline("Test Setting Image that was already loaded by another ImageView and still getting ResourceReadySignal when staged.");
+
+  ToolkitTestApplication application;
+
+  gResourceReadySignalFired = false;
+
+  Property::Map imageImmediateLoadingMap;
+  imageImmediateLoadingMap[ ImageVisual::Property::URL ] = gImage_34_RGBA;
+  imageImmediateLoadingMap[ DevelImageVisual::Property::LOAD_POLICY ] =  DevelImageVisual::LoadPolicy::IMMEDIATE;
+
+  tet_infoline("Immediate load an image");
+  ImageView imageView = ImageView::New();
+  imageView.ResourceReadySignal().Connect( &ResourceReadySignal);
+  imageView.SetProperty( ImageView::Property::IMAGE, imageImmediateLoadingMap );
+
+  // loading started, this waits for the loader thread
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(16);
+
+  tet_infoline("Check image loaded");
+  DALI_TEST_EQUALS( gResourceReadySignalFired, true, TEST_LOCATION );
+  gResourceReadySignalFired = false;
+
+  tet_infoline("Create another ImageView with the same URL");
+  ImageView imageViewWithExistingImage = ImageView::New( gImage_34_RGBA );
+  tet_infoline("Connect to ResourceReady signal for second ImageView, it should still fire as resource is ready");
+  imageViewWithExistingImage.ResourceReadySignal().Connect( &ResourceReadySignal);
+
+  Stage::GetCurrent().Add( imageViewWithExistingImage );
+
+  DALI_TEST_EQUALS( gResourceReadySignalFired, true, TEST_LOCATION );
+
+  END_TEST;
+}
index 3de6688..679721c 100644 (file)
@@ -59,7 +59,6 @@ void ResourceReadySignal( Control control )
   gResourceReadySignalFired = true;
 }
 
-
 Actor CreateActorWithImageVisual(const Property::Map& map)
 {
   VisualFactory factory = VisualFactory::Get();
@@ -1684,44 +1683,145 @@ int UtcDaliImageVisualLoadPolicy02(void)
 int UtcDaliImageVisualLoadPolicy03(void)
 {
   ToolkitTestApplication application;
-  tet_infoline( "UtcDaliImageVisualLoadPolicy03 Load a visual image before attaching to stage and receive ResourceReady signal" );
+  tet_infoline( "UtcDaliImageVisualLoadPolicy03 Load a visual image and receive ResourceReady Signal when loaded" );
+
+  const bool VISUAL_NOT_ENABLED( false ); // Instead of just passing 'false' into an API.
 
   // Set up trace debug
   TestGlAbstraction& gl = application.GetGlAbstraction();
   TraceCallStack& textureTrace = gl.GetTextureTrace();
   textureTrace.Enable(true);
 
+  tet_infoline( "Create a control and connect to resource ready signal without adding to stage" );
+  DummyControl actor = DummyControl::New(true);
+  actor.ResourceReadySignal().Connect( &ResourceReadySignal);
+  Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(actor.GetImplementation());
+  actor.SetSize(200.f, 200.f);
+
   tet_infoline( "Create visual with IMMEDIATE load policy" );
   Visual::Base imageVisual = CreateVisualWithPolicy( TEST_IMAGE_FILE_NAME, DevelImageVisual::Property::LOAD_POLICY, DevelImageVisual::LoadPolicy::IMMEDIATE );
 
-  // Wait for image to load, ResourceReady signal will not be emitted until Visual is registered with a control and on stage.
+  tet_infoline( "Registering visual allows control to get a signal once loaded even if visual not enabled( not staged )" );
+  dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, imageVisual, VISUAL_NOT_ENABLED );
+  imageVisual.Reset(); // reduce ref count so only the control keeps the visual alive.
+
+  tet_infoline( "Allow image time to load resource" );
   DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+  application.SendNotification();
+  application.Render();
 
   // Ensure texture has been uploaded
+  DALI_TEST_EQUALS( textureTrace.FindMethod("GenTextures"), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( gResourceReadySignalFired, true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliImageVisualLoadPolicy04(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline( "UtcDaliImageVisualLoadPolicy04 First part  Load a visual image before attaching to stage");
+  tet_infoline( "Second part, Reuse the same image in aonther control and check resource ready signal fired" );
+
+  const bool VISUAL_NOT_ENABLED( false ); // Instead of just passing false into an API.
+
+  // Set up trace debug
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+  TraceCallStack& textureTrace = gl.GetTextureTrace();
+  textureTrace.Enable(true);
+
+  tet_infoline( "Create a control and connect to resource ready signal" );
+  DummyControl actor = DummyControl::New(true);
+  actor.ResourceReadySignal().Connect( &ResourceReadySignal);
+  Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(actor.GetImplementation());
+  actor.SetSize(200.f, 200.f);
+
+  tet_infoline( "Create visual with IMMEDIATE load policy" );
+  Visual::Base imageVisual = CreateVisualWithPolicy( TEST_IMAGE_FILE_NAME, DevelImageVisual::Property::LOAD_POLICY, DevelImageVisual::LoadPolicy::IMMEDIATE );
+
+  tet_infoline( "Registering visual allows control to get a signal once loaded even if visual not enabled( staged )" );
+  dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, imageVisual, VISUAL_NOT_ENABLED );
+  imageVisual.Reset(); // reduce ref count so only the control keeps the visual alive.
+
+  tet_infoline( "Allow image time to load" );
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
   application.SendNotification();
   application.Render();
 
-  tet_infoline( "Ensure texture loading starts after visual created" );
+  tet_infoline( "Testing texture is loaded and resource ready signal fired" );
   DALI_TEST_EQUALS( textureTrace.FindMethod("GenTextures"), true, TEST_LOCATION );
-  textureTrace.Reset();
+  DALI_TEST_EQUALS( gResourceReadySignalFired, true, TEST_LOCATION );
 
-  tet_infoline( "Register visuals with control and ensure it has the only handles" );
+  tet_infoline( "Original control correctly signalled, now testing for signal with new Control reusing the image" );
+
+  gResourceReadySignalFired = false; // Reset signal check ready for testing next Control
+  Visual::Base imageVisual2 = CreateVisualWithPolicy( TEST_IMAGE_FILE_NAME, DevelImageVisual::Property::LOAD_POLICY, DevelImageVisual::LoadPolicy::IMMEDIATE );
+  DummyControl actor2 = DummyControl::New(true);
+  Impl::DummyControl& dummyImpl2 = static_cast<Impl::DummyControl&>(actor.GetImplementation());
+  actor2.ResourceReadySignal().Connect( &ResourceReadySignal);
+
+  tet_infoline( "Registering visual this should trigger the loading signal as is already image loaded for previous control" );
+  dummyImpl2.RegisterVisual( DummyControl::Property::TEST_VISUAL, imageVisual2 );
+  imageVisual2.Reset(); // reduce ref count so only the control keeps the visual alive.
+  actor2.SetSize(200.f, 200.f);
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 0 ), true, TEST_LOCATION ); // Not expecting any further loading as texture is being reused.
+  DALI_TEST_EQUALS( gResourceReadySignalFired, true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliImageVisualLoadPolicy05(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline( "UtcDaliImageVisualLoadPolicy05 LoadPolicy::ATTACHED (default) First part  Load a visual image before attaching to stage");
+  tet_infoline( "Second part, Reuse the same image in aonther control and check resource ready signal fired" );
+  // Set up trace debug
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+  TraceCallStack& textureTrace = gl.GetTextureTrace();
+  textureTrace.Enable(true);
+
+  tet_infoline( "Create a control and connect to resource ready signal" );
   DummyControl actor = DummyControl::New(true);
   actor.ResourceReadySignal().Connect( &ResourceReadySignal);
   Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(actor.GetImplementation());
+  actor.SetSize(200.f, 200.f);
+  Stage::GetCurrent().Add( actor );
 
-  tet_infoline( "Registering visual attaches it to stage and trigger the loading signal if Image loaded" );
+  tet_infoline( "Create visual with ATTACHED load policy" );
+  Visual::Base imageVisual = CreateVisualWithPolicy( TEST_IMAGE_FILE_NAME, DevelImageVisual::Property::LOAD_POLICY, DevelImageVisual::LoadPolicy::ATTACHED );
+
+  tet_infoline( "Registering visual allows control to get a signal once loaded" );
   dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, imageVisual );
   imageVisual.Reset(); // reduce ref count so only the control keeps the visual alive.
-  actor.SetSize(200.f, 200.f);
-  // Adding the Control hence Visual to stage will cause the Visual to trigger ResourceReadySignal if the image is already loaded.
-  Stage::GetCurrent().Add( actor ); // If LoadPolicy was not IMMEDIATE then as this point (after attached to stage) the test would need to wait for Loading
 
+  tet_infoline( "Allow image time to load" );
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+  application.SendNotification();
+  application.Render();
+
+  tet_infoline( "Testing texture is loaded and resource ready signal fired" );
+  DALI_TEST_EQUALS( textureTrace.FindMethod("GenTextures"), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( gResourceReadySignalFired, true, TEST_LOCATION );
+
+  tet_infoline( "Original control correctly signalled, now testing for signal with new Control reusing the image" );
+
+  gResourceReadySignalFired = false; // Reset signal check ready for testing next Control
+  Visual::Base imageVisual2 = CreateVisualWithPolicy( TEST_IMAGE_FILE_NAME, DevelImageVisual::Property::LOAD_POLICY, DevelImageVisual::LoadPolicy::ATTACHED );
+  DummyControl actor2 = DummyControl::New(true);
+  Impl::DummyControl& dummyImpl2 = static_cast<Impl::DummyControl&>(actor.GetImplementation());
+  actor2.ResourceReadySignal().Connect( &ResourceReadySignal);
+
+  tet_infoline( "Registering visual this should trigger the loading signal as is already image loaded for previous control" );
+  dummyImpl2.RegisterVisual( DummyControl::Property::TEST_VISUAL, imageVisual2 );
+  imageVisual2.Reset(); // reduce ref count so only the control keeps the visual alive.
+  actor2.SetSize(200.f, 200.f);
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 0 ), true, TEST_LOCATION ); // Not expecting any further loading as texture is being reused.
   DALI_TEST_EQUALS( gResourceReadySignalFired, true, TEST_LOCATION );
 
   END_TEST;
 }
 
+
 int UtcDaliImageVisualOrientationCorrection(void)
 {
   ToolkitTestApplication application;
index 6ff1efb..1630b92 100644 (file)
@@ -525,12 +525,17 @@ void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base
                                              ( visualReplaced && enabled ) ) ;
     mVisuals.PushBack( newRegisteredVisual );
 
+    Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
     // Put on stage if enabled and the control is already on the stage
-    // Visual must be set on stage for the renderer to be created and the ResourceReady triggered.
     if( ( enabled == VisualState::ENABLED ) && self.OnStage() )
     {
-      Toolkit::GetImplementation(visual).SetOnStage( self );
+      visualImpl.SetOnStage( self );
     }
+    else if( visualImpl.IsResourceReady() ) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
+    {
+      ResourceReady( visualImpl );
+    }
+
   }
 
   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n",  visual.GetName().c_str(), index, enabled?"true":"false" );
@@ -657,8 +662,11 @@ void Control::Impl::ResourceReady( Visual::Base& object)
     }
   }
 
-  // A visual is ready so control may need relayouting
-  mControlImpl.RelayoutRequest();
+  // A visual is ready so control may need relayouting if staged
+  if ( self.OnStage() )
+  {
+    mControlImpl.RelayoutRequest();
+  }
 
   // Emit signal if all enabled visuals registered by the control are ready.
   if( IsResourceReady() )
index 7ef4669..9afcb29 100644 (file)
@@ -276,14 +276,17 @@ ImageVisual::ImageVisual( VisualFactoryCache& factoryCache,
   mMaskingData( ),
   mDesiredSize( size ),
   mTextureId( TextureManager::INVALID_TEXTURE_ID ),
+  mTextures(),
   mFittingMode( fittingMode ),
   mSamplingMode( samplingMode ),
   mWrapModeU( WrapMode::DEFAULT ),
   mWrapModeV( WrapMode::DEFAULT ),
   mLoadPolicy( DevelImageVisual::LoadPolicy::ATTACHED ),
   mReleasePolicy( DevelImageVisual::ReleasePolicy::DETACHED ),
+  mAtlasRect( 0.0f, 0.0f, 0.0f, 0.0f ),
   mAttemptAtlasing( false ),
-  mLoading( false )
+  mLoading( false ),
+  mOrientationCorrection( true )
 {
 }
 
@@ -296,12 +299,14 @@ ImageVisual::ImageVisual( VisualFactoryCache& factoryCache, const Image& image )
   mMaskingData( ),
   mDesiredSize(),
   mTextureId( TextureManager::INVALID_TEXTURE_ID ),
+  mTextures(),
   mFittingMode( FittingMode::DEFAULT ),
   mSamplingMode( SamplingMode::DEFAULT ),
   mWrapModeU( WrapMode::DEFAULT ),
   mWrapModeV( WrapMode::DEFAULT ),
   mLoadPolicy( DevelImageVisual::LoadPolicy::ATTACHED ),
   mReleasePolicy( DevelImageVisual::ReleasePolicy::DESTROYED ),
+  mAtlasRect( 0.0f, 0.0f, 0.0f, 0.0f ),
   mAttemptAtlasing( false ),
   mLoading( false ),
   mOrientationCorrection( true )
@@ -1035,6 +1040,8 @@ void ImageVisual::UploadCompleted()
     // reset the weak handle so that the renderer only get added to actor once
     mPlacementActor.Reset();
   }
+  // Image loaded
+  ResourceReady( Toolkit::Visual::ResourceStatus::READY );
   mLoading = false;
 }
 
@@ -1061,8 +1068,6 @@ void ImageVisual::UploadComplete( bool loadingSuccess, int32_t textureId, Textur
         sampler.SetWrapMode(  mWrapModeU, mWrapModeV  );
         textureSet.SetSampler( 0u, sampler );
         mImpl->mRenderer.SetTextures(textureSet);
-
-        resourceStatus = Toolkit::Visual::ResourceStatus::READY;
       }
       else
       {
@@ -1072,20 +1077,26 @@ void ImageVisual::UploadComplete( bool loadingSuccess, int32_t textureId, Textur
         mImpl->mRenderer.SetTextures( textureSet );
 
         ApplyImageToSampler( brokenImage );
-
-        resourceStatus = Toolkit::Visual::ResourceStatus::FAILED;
       }
-      // Image loaded and ready to display
-      ResourceReady( resourceStatus );
     }
   }
-
   // Storing TextureSet needed when renderer staged.
   if( ! mImpl->mRenderer )
   {
     mTextures = textureSet;
   }
 
+  // Image loaded, set status regardless of staged status.
+  if( loadingSuccess )
+  {
+    resourceStatus = Toolkit::Visual::ResourceStatus::READY;
+  }
+  else
+  {
+    resourceStatus = Toolkit::Visual::ResourceStatus::FAILED;
+  }
+  // Signal to observers ( control ) that resources are ready. Must be all resources.
+  ResourceReady( resourceStatus );
   mLoading = false;
 }
 
index 6d2f7e7..eee3b91 100644 (file)
@@ -450,6 +450,23 @@ public:
    *
    * Most resources are only loaded when the control is placed on stage.
    *
+   * If resources are shared between ImageViews, they are cached.
+   * In this case, the ResourceReady signal may be sent before there is an object to connect to.
+   * To protect against this, IsResourceReady() can be checked first.
+   *
+   * @code
+   *    auto newControl = Control::New();
+   *    newControl.SetResource( resourceUrl );
+   *    if ( newControl.IsResourceReady() )
+   *    {
+   *       // do something
+   *    }
+   *    else
+   *    {
+   *      newControl.ResourceReadySignal.Connect( .... )
+   *    }
+   * @endcode
+   *
    * A callback of the following type may be connected:
    * @code
    *   void YourCallbackName( Control control );
index 69bcbc3..b6f786b 100644 (file)
@@ -44,6 +44,32 @@ class ImageView;
  *
  * An instance of ImageView can be created using a URL or an Image instance.
  *
+ * Some resources can be loaded before the ImageView is staged ( already cached ), in these cases if the connection to
+ * ResouceReadySignal is done after the resource is set then signal will be missed.
+ *
+ * To protect against this, IsResourceReady() can be checked before connecting to ResourceReadySignal,
+ * or the signal connection can be done before setting the resource"
+ *
+ * @code
+ *    auto myImageView = ImageView::New( resourceUrl );
+ *    if ( myImageView.IsResourceReady() )
+ *    {
+ *       // do something
+ *    }
+ *    else
+ *    {
+ *      myImageView.ResourceReadySignal.Connect( .... )
+ *    }
+ * @endcode
+ *
+ * OR Connect to signal before setting resource
+ *
+ * @code
+ *    auto myImageView = ImageView::New( resourceUrl );
+ *    myImageView.ResourceReadySignal.Connect( .... )
+ *    myImageView.SetProperty( ImageView::Property::IMAGE, resourceUrl );
+ * @endcode
+ *
  * @SINCE_1_0.0
  *
  */
index 43fe66a..04888a1 100644 (file)
@@ -30,8 +30,8 @@ namespace Toolkit
 {
 
 const unsigned int TOOLKIT_MAJOR_VERSION = 1;
-const unsigned int TOOLKIT_MINOR_VERSION = 2;
-const unsigned int TOOLKIT_MICRO_VERSION = 65;
+const unsigned int TOOLKIT_MINOR_VERSION = 3;
+const unsigned int TOOLKIT_MICRO_VERSION = 0;
 const char * const TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index 4f57197..e3ec0df 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali-toolkit
 Summary:    Dali 3D engine Toolkit
-Version:    1.2.65
+Version:    1.3.0
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT