Merge branch 'devel/master' into tizen
authorHosang Kim <hosang12.kim@samsung.com>
Mon, 25 Jul 2022 05:28:54 +0000 (14:28 +0900)
committerHosang Kim <hosang12.kim@samsung.com>
Mon, 25 Jul 2022 05:28:54 +0000 (14:28 +0900)
19 files changed:
automated-tests/src/dali/utc-Dali-Actor.cpp
automated-tests/src/dali/utc-Dali-Constraint.cpp
automated-tests/src/dali/utc-Dali-CustomActor.cpp
automated-tests/src/dali/utc-Dali-Pixel.cpp
automated-tests/src/dali/utc-Dali-Texture.cpp
dali/devel-api/rendering/texture-devel.cpp
dali/devel-api/rendering/texture-devel.h
dali/internal/event/animation/constraint-impl.h
dali/internal/event/common/property-metadata.cpp
dali/internal/event/events/hit-test-algorithm-impl.cpp
dali/internal/event/rendering/decorated-visual-renderer-impl.cpp
dali/internal/event/rendering/texture-impl.cpp
dali/internal/event/rendering/texture-impl.h
dali/internal/render/renderers/render-texture.cpp
dali/internal/update/manager/render-instruction-processor.cpp
dali/public-api/dali-core-version.cpp
dali/public-api/images/pixel.cpp
dali/public-api/images/pixel.h
packaging/dali.spec

index 32ff0fb..e233914 100644 (file)
@@ -9343,6 +9343,55 @@ int utcDaliActorPartialUpdateChangeTransparency(void)
   application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
   application.RenderWithPartialUpdate(damagedRects, clippingRect);
 
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+  // Make the actor translucent
+  renderer[DevelRenderer::Property::OPACITY] = 0.5f;
+
+  application.SendNotification();
+
+  // The damaged rect should not be empty
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+  // Change Renderer opacity - also translucent
+  renderer[DevelRenderer::Property::OPACITY] = 0.2f;
+
+  application.SendNotification();
+
+  // The damaged rect should not be empty
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
   // Make the actor culled
   actor[Actor::Property::SIZE] = Vector3(0.0f, 0.0f, 0.0f);
 
@@ -10499,4 +10548,4 @@ int UtcDaliActorAllowOnlyOwnTouchPropertyN(void)
     tet_result(TET_FAIL);
   }
   END_TEST;
-}
\ No newline at end of file
+}
index c215e84..30b361f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -259,6 +259,7 @@ int UtcDaliConstraintNewFunctorN(void)
 
   END_TEST;
 }
+
 ///////////////////////////////////////////////////////////////////////////////
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1559,3 +1560,72 @@ int UtcDaliConstraintGetTagNegative(void)
   }
   END_TEST;
 }
+
+namespace ComponentTest
+{
+void CheckComponentProperty(TestApplication& application, Actor& actor, Property::Index property)
+{
+  float value = actor.GetCurrentProperty<float>(property);
+
+  // Add a component 0 constraint
+  RelativeToConstraintFloat relativeConstraint(2.0f);
+  Constraint                constraint = Constraint::New<float>(actor, property, relativeConstraint);
+  constraint.AddSource(Source{actor, property});
+  DALI_TEST_CHECK(constraint);
+  constraint.SetRemoveAction(Constraint::RemoveAction::DISCARD);
+  constraint.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(actor.GetCurrentProperty<float>(property), value * 2.0f, TEST_LOCATION);
+
+  constraint.Remove();
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(actor.GetCurrentProperty<float>(property), value, TEST_LOCATION);
+}
+} // namespace ComponentTest
+
+int UtcDaliConstraintComponentTransformPropertyConstraintP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetProperty(Actor::Property::POSITION, Vector3(100.0f, 100.0f, 100.0f));
+  application.GetScene().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(actor.GetCurrentProperty<Vector3>(Actor::Property::POSITION), Vector3(100.0f, 100.0f, 100.0f), TEST_LOCATION);
+
+  ComponentTest::CheckComponentProperty(application, actor, Actor::Property::POSITION_X); // Component 0
+  ComponentTest::CheckComponentProperty(application, actor, Actor::Property::POSITION_Y); // Component 1
+  ComponentTest::CheckComponentProperty(application, actor, Actor::Property::POSITION_Z); // Component 2
+
+  END_TEST;
+}
+
+int UtcDaliConstraintComponentNonTransformPropertyConstraintP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetProperty(Actor::Property::COLOR, Vector4(0.25f, 0.25f, 0.25f, 0.25f));
+  application.GetScene().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(actor.GetCurrentProperty<Vector4>(Actor::Property::COLOR), Vector4(0.25f, 0.25f, 0.25f, 0.25f), TEST_LOCATION);
+
+  ComponentTest::CheckComponentProperty(application, actor, Actor::Property::COLOR_RED);   // Component 0
+  ComponentTest::CheckComponentProperty(application, actor, Actor::Property::COLOR_GREEN); // Component 1
+  ComponentTest::CheckComponentProperty(application, actor, Actor::Property::COLOR_BLUE);  // Component 2
+  ComponentTest::CheckComponentProperty(application, actor, Actor::Property::COLOR_ALPHA); // Component 3
+
+  END_TEST;
+}
\ No newline at end of file
index e33a738..1df10a6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 using namespace Dali;
 
+namespace Test
+{
+void Doubler(float& current, const PropertyInputContainer& inputs)
+{
+  current = 2.0f * inputs[0]->GetFloat();
+}
+} // namespace Test
+
 void custom_actor_test_startup(void)
 {
   test_return_value = TET_UNDEF;
@@ -1609,3 +1617,95 @@ int UtcDaliCustomActorPropertyRegistrationDefaultValue(void)
 
   END_TEST;
 }
+
+int UtcDaliCustomActorComponentPropertyConstraintsP(void)
+{
+  TestApplication application; // Need the type registry
+
+  // register our base and add a property with default value for it
+  Dali::TypeRegistration typeRegistration(typeid(UnregisteredCustomActor), typeid(Dali::CustomActor), nullptr);
+
+  auto derived = DerivedCustomActor::New();
+  application.GetScene().Add(derived);
+
+  // should have all actor properties
+  auto actorHandle = Actor::New();
+  DALI_TEST_EQUALS(derived.GetPropertyCount(), actorHandle.GetPropertyCount(), TEST_LOCATION);
+
+  // add a property in base class
+  const Property::Index foobarIndex = ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX;
+  const Property::Index fooIndex    = foobarIndex + 1;
+  const Property::Index barIndex    = foobarIndex + 2;
+
+  AnimatablePropertyRegistration(typeRegistration, "Foobar", foobarIndex, Vector2(10.0f, 20.0f));
+  AnimatablePropertyComponentRegistration(typeRegistration, "Foobar.x", fooIndex, foobarIndex, 0);
+  AnimatablePropertyComponentRegistration(typeRegistration, "Foobar.y", barIndex, foobarIndex, 1);
+
+  tet_infoline("Test the default values of the registered property");
+  // should be more properties now
+  DALI_TEST_EQUALS(derived.GetPropertyCount(), actorHandle.GetPropertyCount() + 3, TEST_LOCATION);
+  // check that the default value is set for base class
+  DALI_TEST_EQUALS(UnregisteredCustomActor::New().GetProperty(foobarIndex).Get<Vector2>(), Vector2(10.f, 20.0f), 0.0001f, TEST_LOCATION);
+  // check that the default value is set for the derived instance as well
+  DALI_TEST_EQUALS(derived.GetProperty(foobarIndex).Get<Vector2>(), Vector2(10.f, 20.0f), 0.0001f, TEST_LOCATION);
+
+  tet_infoline("Test that the components of the registered property can be constrained");
+
+  // Try constraining the properties
+  Constraint fooCons = Constraint::New<float>(derived, fooIndex, &Test::Doubler);
+  fooCons.AddSource(LocalSource(Actor::Property::POSITION_X));
+  fooCons.Apply();
+  Constraint barCons = Constraint::New<float>(derived, barIndex, &Test::Doubler);
+  barCons.AddSource(LocalSource(fooIndex));
+  barCons.Apply();
+
+  for(int i = 1; i < 10; ++i)
+  {
+    derived[Actor::Property::POSITION_X] = i * 1.0f;
+    application.SendNotification();
+    application.Render();
+    DALI_TEST_EQUALS(derived.GetCurrentProperty(foobarIndex).Get<Vector2>(), Vector2(i * 2.0f, i * 4.0f), 0.0001f, TEST_LOCATION);
+  }
+
+  // Add a Vector3 property and its components for completeness
+  const Property::Index vec3PropIndex  = barIndex + 1;
+  const Property::Index vec3xPropIndex = vec3PropIndex + 1;
+  const Property::Index vec3yPropIndex = vec3PropIndex + 2;
+  const Property::Index vec3zPropIndex = vec3PropIndex + 3;
+
+  AnimatablePropertyRegistration(typeRegistration, "vec3Prop", vec3PropIndex, Vector3(10.0f, 20.0f, 30.0f));
+  AnimatablePropertyComponentRegistration(typeRegistration, "vec3Prop.x", vec3xPropIndex, vec3PropIndex, 0);
+  AnimatablePropertyComponentRegistration(typeRegistration, "vec3Prop.y", vec3yPropIndex, vec3PropIndex, 1);
+  AnimatablePropertyComponentRegistration(typeRegistration, "vec3Prop.z", vec3zPropIndex, vec3PropIndex, 2);
+
+  tet_infoline("Test the default values of the registered vec3 property");
+  // should be more properties now
+  DALI_TEST_EQUALS(derived.GetPropertyCount(), actorHandle.GetPropertyCount() + 7, TEST_LOCATION);
+  // check that the default value is set for base class
+  DALI_TEST_EQUALS(UnregisteredCustomActor::New().GetProperty(vec3PropIndex).Get<Vector3>(), Vector3(10.f, 20.0f, 30.0f), 0.0001f, TEST_LOCATION);
+  // check that the default value is set for the derived instance as well
+  DALI_TEST_EQUALS(derived.GetProperty(vec3PropIndex).Get<Vector3>(), Vector3(10.f, 20.0f, 30.0f), 0.0001f, TEST_LOCATION);
+
+  tet_infoline("Test that the components of the registered property can be constrained");
+
+  // Try constraining the properties
+  Constraint vec3xConstraint = Constraint::New<float>(derived, vec3xPropIndex, &Test::Doubler);
+  vec3xConstraint.AddSource(LocalSource(Actor::Property::POSITION_X));
+  vec3xConstraint.Apply();
+  Constraint vec3yConstraint = Constraint::New<float>(derived, vec3yPropIndex, &Test::Doubler);
+  vec3yConstraint.AddSource(LocalSource(vec3xPropIndex));
+  vec3yConstraint.Apply();
+  Constraint vec3zConstraint = Constraint::New<float>(derived, vec3zPropIndex, &Test::Doubler);
+  vec3zConstraint.AddSource(LocalSource(vec3yPropIndex));
+  vec3zConstraint.Apply();
+
+  for(int i = 1; i < 10; ++i)
+  {
+    derived[Actor::Property::POSITION_X] = i * 1.0f;
+    application.SendNotification();
+    application.Render();
+    DALI_TEST_EQUALS(derived.GetCurrentProperty(vec3PropIndex).Get<Vector3>(), Vector3(i * 2.0f, i * 4.0f, i * 8.0f), 0.0001f, TEST_LOCATION);
+  }
+
+  END_TEST;
+}
index 6eb1948..8e991e9 100644 (file)
@@ -43,6 +43,94 @@ static void TestPixelEnumSize(const int size)
                   "The Pixel::Format enum may have had new formats added. Expand the test cases to include them.");
 }
 
+int UtcDaliPixelIsCompressed(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliPixelIsCompressed");
+
+  TestPixelEnumSize(62);
+
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::INVALID) == false); // For completeness
+
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::L8) == false);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::RGB565) == false);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::RGB888) == false);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::RGB8888) == false);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::BGR8888) == false);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::BGR565) == false);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_R11_EAC) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SIGNED_R11_EAC) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RG11_EAC) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SIGNED_RG11_EAC) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGB8_ETC2) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ETC2) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGB8_ETC1) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGB_PVRTC_4BPPV1) == true);
+
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::A8) == false);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::LA88) == false);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::RGBA5551) == false);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::RGBA4444) == false);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::RGBA8888) == false);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::BGRA8888) == false);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::BGRA5551) == false);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::BGRA4444) == false);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA8_ETC2_EAC) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC) == true);
+
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_4x4_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_5x4_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_5x5_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_6x5_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_6x6_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_8x5_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_8x6_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_8x8_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_10x5_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_10x6_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_10x8_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_10x10_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_12x10_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_12x12_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR) == true);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR) == true);
+
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::RGB16F) == false);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::RGB32F) == false);
+
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::DEPTH_UNSIGNED_INT) == false);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::DEPTH_FLOAT) == false);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::DEPTH_STENCIL) == false);
+
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::R11G11B10F) == false);
+
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::CHROMINANCE_U) == false);
+  DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::CHROMINANCE_V) == false);
+
+  END_TEST;
+}
+
+int UtcDaliPixelIsCompressedN(void)
+{
+  DALI_TEST_EQUALS(Pixel::IsCompressed(Pixel::Format(123123123123)), false, TEST_LOCATION);
+  END_TEST;
+}
+
 int UtcDaliPixelHasAlpha(void)
 {
   TestApplication application;
index 5de38f2..b16d10b 100644 (file)
@@ -206,9 +206,9 @@ int UtcDaliTextureUpload01(void)
 
   //Upload part of the texture
   callStack.Reset();
-  bufferSize                  = width * height * 2;
+  bufferSize                  = width * height;
   buffer                      = reinterpret_cast<unsigned char*>(malloc(bufferSize));
-  PixelData pixelDataSubImage = PixelData::New(buffer, bufferSize, width, height, Pixel::RGBA8888, PixelData::FREE);
+  PixelData pixelDataSubImage = PixelData::New(buffer, bufferSize, width / 2, height / 2, Pixel::RGBA8888, PixelData::FREE);
   texture.Upload(pixelDataSubImage, 0u, 0u, width / 2, height / 2, width / 2, height / 2);
   application.SendNotification();
   application.Render();
@@ -382,7 +382,7 @@ int UtcDaliTextureUpload03(void)
 
   bufferSize                 = widthMipmap1 * heightMipmap1 * 4;
   buffer                     = reinterpret_cast<unsigned char*>(malloc(bufferSize));
-  PixelData pixelDataMipmap1 = PixelData::New(buffer, bufferSize, width, height, Pixel::RGBA8888, PixelData::FREE);
+  PixelData pixelDataMipmap1 = PixelData::New(buffer, bufferSize, widthMipmap1, heightMipmap1, Pixel::RGBA8888, PixelData::FREE);
   texture.Upload(pixelDataMipmap1, 0u, 1u, 0u, 0u, widthMipmap1, heightMipmap1);
   application.SendNotification();
   application.Render();
@@ -425,7 +425,7 @@ int UtcDaliTextureUpload04(void)
 
   bufferSize                 = widthMipmap1 * heightMipmap1 * 4;
   buffer                     = reinterpret_cast<unsigned char*>(malloc(bufferSize));
-  PixelData pixelDataMipmap1 = PixelData::New(buffer, bufferSize, width, height, Pixel::RGBA8888, PixelData::FREE);
+  PixelData pixelDataMipmap1 = PixelData::New(buffer, bufferSize, widthMipmap1, heightMipmap1, Pixel::RGBA8888, PixelData::FREE);
   texture.Upload(pixelDataMipmap1, CubeMapLayer::NEGATIVE_X, 1u, 0u, 0u, widthMipmap1, heightMipmap1);
   application.SendNotification();
   application.Render();
@@ -534,9 +534,9 @@ int UtcDaliTextureUpload05(void)
 
     //Upload part of the texture
     callStack.Reset();
-    bufferSize                  = width * height * 2;
+    bufferSize                  = width * height;
     buffer                      = reinterpret_cast<unsigned char*>(malloc(bufferSize));
-    PixelData pixelDataSubImage = PixelData::New(buffer, bufferSize, width, height, COMPRESSED_PIXEL_FORMATS[index], PixelData::FREE);
+    PixelData pixelDataSubImage = PixelData::New(buffer, bufferSize, width / 2, height / 2, COMPRESSED_PIXEL_FORMATS[index], PixelData::FREE);
     texture.Upload(pixelDataSubImage, 0u, 0u, width / 2, height / 2, width / 2, height / 2);
     application.SendNotification();
     application.Render();
@@ -654,6 +654,188 @@ int UtcDaliTextureUpload07(void)
   END_TEST;
 }
 
+int UtcDaliTextureUploadSubPixelData01(void)
+{
+  TestApplication application;
+
+  //Create the texture
+  unsigned int width(64);
+  unsigned int height(64);
+  Texture      texture = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, width, height);
+
+  application.GetGlAbstraction().EnableTextureCallTrace(true);
+
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace();
+
+  //Upload data to the texture
+  callStack.Reset();
+
+  uint32_t bufferWidth   = width * 2;
+  uint32_t bufferHeight  = height * 2;
+  uint32_t bufferXOffset = width;
+  uint32_t bufferYOffset = height;
+
+  unsigned int   bufferSize(bufferWidth * bufferHeight * 4);
+  unsigned char* buffer    = reinterpret_cast<unsigned char*>(malloc(bufferSize));
+  PixelData      pixelData = PixelData::New(buffer, bufferSize, bufferWidth, bufferHeight, Pixel::RGBA8888, PixelData::FREE);
+  DevelTexture::UploadSubPixelData(texture, pixelData, bufferXOffset, bufferYOffset, width, height);
+  application.SendNotification();
+  application.Render();
+
+  //TexImage2D should be called to upload the data
+  {
+    std::stringstream out;
+    out << GL_TEXTURE_2D << ", " << 0u << ", " << width << ", " << height;
+    DALI_TEST_CHECK(callStack.FindMethodAndParams("TexImage2D", out.str().c_str()));
+  }
+
+  //Upload part of the texture
+  callStack.Reset();
+  DevelTexture::UploadSubPixelData(texture, pixelData, bufferXOffset, bufferYOffset, width / 2, height / 2, 0u, 0u, width / 2, height / 2, width / 2, height / 2);
+  application.SendNotification();
+  application.Render();
+
+  //TexSubImage2D should be called to upload the data
+  {
+    std::stringstream out;
+    out << GL_TEXTURE_2D << ", " << 0u << ", " << width / 2 << ", " << height / 2 << ", " << width / 2 << ", " << height / 2;
+    DALI_TEST_CHECK(callStack.FindMethodAndParams("TexSubImage2D", out.str().c_str()));
+  }
+
+  END_TEST;
+}
+
+int UtcDaliTextureUploadSubPixelData02(void)
+{
+  TestApplication application;
+
+  //Create the texture
+  unsigned int width(64);
+  unsigned int height(64);
+  Texture      texture = CreateTexture(TextureType::TEXTURE_CUBE, Pixel::RGBA8888, width, height);
+
+  application.GetGlAbstraction().EnableTextureCallTrace(true);
+
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace();
+
+  tet_infoline("TexImage2D should be called six times with a null pointer to reserve storage for the six textures of the cube map");
+  for(unsigned int i(0); i < 6; ++i)
+  {
+    std::stringstream out;
+    out << GL_TEXTURE_CUBE_MAP_POSITIVE_X + i << ", " << 0u << ", " << width << ", " << height;
+    DALI_TEST_CHECK(callStack.FindMethodAndParams("TexImage2D", out.str().c_str()));
+  }
+
+  uint32_t bufferWidth   = width * 2;
+  uint32_t bufferHeight  = height * 2;
+  uint32_t bufferXOffset = width;
+  uint32_t bufferYOffset = height;
+
+  unsigned int   bufferSize(bufferWidth * bufferHeight * 4);
+  unsigned char* buffer    = reinterpret_cast<unsigned char*>(malloc(bufferSize));
+  PixelData      pixelData = PixelData::New(buffer, bufferSize, bufferWidth, bufferHeight, Pixel::RGBA8888, PixelData::FREE);
+
+  //Upload data to the POSITIVE_X face of the texture
+  {
+    callStack.Reset();
+
+    DevelTexture::UploadSubPixelData(texture, pixelData, bufferXOffset, bufferYOffset, width, height, CubeMapLayer::POSITIVE_X, 0u, 0u, 0u, width, height);
+    application.SendNotification();
+    application.Render();
+
+    //TexImage2D should be called to upload the data to the POSITIVE_X face
+    {
+      std::stringstream out;
+      out << GL_TEXTURE_CUBE_MAP_POSITIVE_X << ", " << 0u << ", " << width << ", " << height;
+      DALI_TEST_CHECK(callStack.FindMethodAndParams("TexImage2D", out.str().c_str()));
+    }
+  }
+
+  //Upload data to the NEGATIVE_X face of the texture
+  {
+    callStack.Reset();
+
+    DevelTexture::UploadSubPixelData(texture, pixelData, bufferXOffset, bufferYOffset, width, height, CubeMapLayer::NEGATIVE_X, 0u, 0u, 0u, width, height);
+    application.SendNotification();
+    application.Render();
+
+    //TexImage2D should be called to upload the data to the NEGATIVE_X face
+    {
+      std::stringstream out;
+      out << GL_TEXTURE_CUBE_MAP_NEGATIVE_X << ", " << 0u << ", " << width << ", " << height;
+      DALI_TEST_CHECK(callStack.FindMethodAndParams("TexImage2D", out.str().c_str()));
+    }
+  }
+
+  //Upload data to the POSITIVE_Y face of the texture
+  {
+    callStack.Reset();
+    DevelTexture::UploadSubPixelData(texture, pixelData, bufferXOffset, bufferYOffset, width, height, CubeMapLayer::POSITIVE_Y, 0u, 0u, 0u, width, height);
+    application.SendNotification();
+    application.Render();
+
+    //TexImage2D should be called to upload the data to the POSITIVE_Y face
+    {
+      std::stringstream out;
+      out << GL_TEXTURE_CUBE_MAP_POSITIVE_Y << ", " << 0u << ", " << width << ", " << height;
+      DALI_TEST_CHECK(callStack.FindMethodAndParams("TexImage2D", out.str().c_str()));
+    }
+  }
+
+  //Upload data to the NEGATIVE_Y face of the texture
+  {
+    callStack.Reset();
+    DevelTexture::UploadSubPixelData(texture, pixelData, bufferXOffset, bufferYOffset, width, height, CubeMapLayer::NEGATIVE_Y, 0u, 0u, 0u, width, height);
+    application.SendNotification();
+    application.Render();
+
+    //TexImage2D should be called to upload the data to the NEGATIVE_Y face
+    {
+      std::stringstream out;
+      out << GL_TEXTURE_CUBE_MAP_NEGATIVE_Y << ", " << 0u << ", " << width << ", " << height;
+      DALI_TEST_CHECK(callStack.FindMethodAndParams("TexImage2D", out.str().c_str()));
+    }
+  }
+
+  //Upload data to the POSITIVE_Z face of the texture
+  {
+    callStack.Reset();
+    DevelTexture::UploadSubPixelData(texture, pixelData, bufferXOffset, bufferYOffset, width, height, CubeMapLayer::POSITIVE_Z, 0u, 0u, 0u, width, height);
+    application.SendNotification();
+    application.Render();
+
+    //TexImage2D should be called to upload the data to the POSITIVE_Z face
+    {
+      std::stringstream out;
+      out << GL_TEXTURE_CUBE_MAP_POSITIVE_Z << ", " << 0u << ", " << width << ", " << height;
+      DALI_TEST_CHECK(callStack.FindMethodAndParams("TexImage2D", out.str().c_str()));
+    }
+  }
+
+  //Upload data to the NEGATIVE_Z face of the texture
+  {
+    callStack.Reset();
+    DevelTexture::UploadSubPixelData(texture, pixelData, bufferXOffset, bufferYOffset, width, height, CubeMapLayer::NEGATIVE_Z, 0u, 0u, 0u, width, height);
+    application.SendNotification();
+    application.Render();
+
+    //TexImage2D should be called to upload the data to the NEGATIVE_Z face
+    {
+      std::stringstream out;
+      out << GL_TEXTURE_CUBE_MAP_NEGATIVE_Z << ", " << 0u << ", " << width << ", " << height;
+      DALI_TEST_CHECK(callStack.FindMethodAndParams("TexImage2D", out.str().c_str()));
+    }
+  }
+
+  END_TEST;
+}
+
 int UtcDaliTextureUploadPixelFormats(void)
 {
   TestApplication application;
index d56cae6..010a51f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -33,5 +33,33 @@ bool ApplyNativeFragmentShader(Dali::Texture texture, std::string& shader)
   return impl.ApplyNativeFragmentShader(shader);
 }
 
+bool UploadSubPixelData(Texture   texture,
+                        PixelData pixelData,
+                        uint32_t  dataXOffset,
+                        uint32_t  dataYOffset,
+                        uint32_t  dataWidth,
+                        uint32_t  dataHeight)
+{
+  Internal::PixelData& internalPixelData = GetImplementation(pixelData);
+  return GetImplementation(texture).UploadSubPixelData(&internalPixelData, dataXOffset, dataYOffset, dataWidth, dataHeight);
+}
+
+bool UploadSubPixelData(Texture   texture,
+                        PixelData pixelData,
+                        uint32_t  dataXOffset,
+                        uint32_t  dataYOffset,
+                        uint32_t  dataWidth,
+                        uint32_t  dataHeight,
+                        uint32_t  layer,
+                        uint32_t  mipmap,
+                        uint32_t  xOffset,
+                        uint32_t  yOffset,
+                        uint32_t  width,
+                        uint32_t  height)
+{
+  Internal::PixelData& internalPixelData = GetImplementation(pixelData);
+  return GetImplementation(texture).UploadSubPixelData(&internalPixelData, dataXOffset, dataYOffset, dataWidth, dataHeight, layer, mipmap, xOffset, yOffset, width, height);
+}
+
 } // namespace DevelTexture
 } // namespace Dali
index 0204a41..9c071e0 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TEXTURE_DEVEL_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -44,6 +44,60 @@ bool DALI_CORE_API IsNative(Dali::Texture texture);
  */
 bool DALI_CORE_API ApplyNativeFragmentShader(Dali::Texture texture, std::string& shader);
 
+/**
+ * @brief Uploads data to the texture from a PixelData object.
+ * @note Compressed type doesn't support this API.
+ * @note Upload does not upsample or downsample pixel data to fit the specified rectangular area in the texture.
+ *
+ * @SINCE_2_1.33
+ * @param[in] texture The texture will be uploaded
+ * @param[in] pixelData The pixelData object
+ * @param[in] dataXOffset Specifies an horizontal offset of the rectangular area in the pixelData that will be updated
+ * @param[in] dataYOffset Specifies a vertical offset of the rectangular area in the pixelData that will be updated
+ * @param[in] dataWidth Specifies the width of the rectangular area in the pixelData that will be updated
+ * @param[in] dataHeight Specifies the height of the rectangular area in the pixelData that will be updated
+ * @return True if the PixelData object has compatible pixel format and fits within the texture, false otherwise
+ */
+bool DALI_CORE_API UploadSubPixelData(Dali::Texture   texture,
+                                      Dali::PixelData pixelData,
+                                      uint32_t        dataXOffset,
+                                      uint32_t        dataYOffset,
+                                      uint32_t        dataWidth,
+                                      uint32_t        dataHeight);
+
+/**
+ * @brief Uploads data to the texture from a PixelData object.
+ * @note Compressed type doesn't support this API.
+ * @note Upload does not upsample or downsample pixel data to fit the specified rectangular area in the texture.
+ *
+ * @SINCE_2_1.33
+ * @param[in] texture The texture will be uploaded
+ * @param[in] pixelData The pixelData object
+ * @param[in] dataXOffset Specifies an horizontal offset of the rectangular area in the pixelData that will be updated
+ * @param[in] dataYOffset Specifies a vertical offset of the rectangular area in the pixelData that will be updated
+ * @param[in] dataWidth Specifies the width of the rectangular area in the pixelData that will be updated
+ * @param[in] dataHeight Specifies the height of the rectangular area in the pixelData that will be updated
+ * @param[in] layer Specifies the layer of a cube map or array texture (Unused for 2D textures). @see CubeMapLayer
+ * @param[in] mipmap Specifies the level-of-detail number. Level 0 is the base image level. Level n is the nth mipmap reduction image
+ * @param[in] xOffset Specifies an horizontal offset of the rectangular area in the texture that will be updated
+ * @param[in] yOffset Specifies a vertical offset of the rectangular area in the texture that will be updated
+ * @param[in] width Specifies the width of the rectangular area in the texture that will be updated
+ * @param[in] height Specifies the height of the rectangular area in the texture that will be updated
+ * @return True if the PixelData object has compatible pixel format and fits within the texture, false otherwise
+ */
+bool DALI_CORE_API UploadSubPixelData(Dali::Texture   texture,
+                                      Dali::PixelData pixelData,
+                                      uint32_t        dataXOffset,
+                                      uint32_t        dataYOffset,
+                                      uint32_t        dataWidth,
+                                      uint32_t        dataHeight,
+                                      uint32_t        layer,
+                                      uint32_t        mipmap,
+                                      uint32_t        xOffset,
+                                      uint32_t        yOffset,
+                                      uint32_t        width,
+                                      uint32_t        height);
+
 } // namespace DevelTexture
 } // namespace Dali
 
index b7b1a3b..7b7ec26 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_ACTIVE_CONSTRAINT_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -290,87 +290,7 @@ private:
       }
       else
       {
-        // Expecting Vector2, Vector3 or Vector4 type
-        if(PropertyTypes::Get<Vector2>() == targetProperty->GetType())
-        {
-          // Constrain float component of Vector2 property
-          if(0 == componentIndex)
-          {
-            mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector2> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
-          }
-          else if(1 == componentIndex)
-          {
-            mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector2> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
-          }
-          resetterRequired = (mSceneGraphConstraint != nullptr);
-        }
-        else if(PropertyTypes::Get<Vector3>() == targetProperty->GetType())
-        {
-          // Constrain float component of Vector3 property
-          if(targetProperty->IsTransformManagerProperty())
-          {
-            if(0 == componentIndex)
-            {
-              mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 0> >::New(*targetProperty,
-                                                                                                                                 propertyOwners,
-                                                                                                                                 func,
-                                                                                                                                 mRemoveAction);
-            }
-            else if(1 == componentIndex)
-            {
-              mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 1> >::New(*targetProperty,
-                                                                                                                                 propertyOwners,
-                                                                                                                                 func,
-                                                                                                                                 mRemoveAction);
-            }
-            else if(2 == componentIndex)
-            {
-              mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 2> >::New(*targetProperty,
-                                                                                                                                 propertyOwners,
-                                                                                                                                 func,
-                                                                                                                                 mRemoveAction);
-            }
-            // Do not create a resetter for transform manager property
-          }
-          else
-          {
-            if(0 == componentIndex)
-            {
-              mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
-            }
-            else if(1 == componentIndex)
-            {
-              mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
-            }
-            else if(2 == componentIndex)
-            {
-              mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorZ<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
-            }
-            resetterRequired = (mSceneGraphConstraint != nullptr);
-          }
-        }
-        else if(PropertyTypes::Get<Vector4>() == targetProperty->GetType())
-        {
-          // Constrain float component of Vector4 property
-          if(0 == componentIndex)
-          {
-            mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
-          }
-          else if(1 == componentIndex)
-          {
-            mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
-          }
-          else if(2 == componentIndex)
-          {
-            mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorZ<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
-          }
-          else if(3 == componentIndex)
-          {
-            mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorW<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
-          }
-
-          resetterRequired = (mSceneGraphConstraint != nullptr);
-        }
+        CreateComponentConstraint(targetProperty, componentIndex, propertyOwners, func, resetterRequired);
       }
       if(mSceneGraphConstraint)
       {
@@ -415,6 +335,99 @@ private:
     return func;
   }
 
+  /**
+   * Creates a component property constraint.
+   * @param[in] targetProperty The target property
+   * @param[in] componentIndex The index of the component
+   * @param[in] propertyOwners The owners of the property
+   * @param[in] func The constraint function
+   * @param[in/out] resetterRequired Set to true if a property resetter is required after creating this constraint
+   */
+  void CreateComponentConstraint(const SceneGraph::PropertyBase* targetProperty, const int32_t componentIndex, SceneGraph::PropertyOwnerContainer& propertyOwners, ConstraintFunctionPtr& func, bool& resetterRequired)
+  {
+    // Expecting Vector2, Vector3 or Vector4 type
+    if(PropertyTypes::Get<Vector2>() == targetProperty->GetType())
+    {
+      // Constrain float component of Vector2 property
+      if(0 == componentIndex)
+      {
+        mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector2> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
+      }
+      else if(1 == componentIndex)
+      {
+        mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector2> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
+      }
+      resetterRequired = (mSceneGraphConstraint != nullptr);
+    }
+    else if(PropertyTypes::Get<Vector3>() == targetProperty->GetType())
+    {
+      // Constrain float component of Vector3 property
+      if(targetProperty->IsTransformManagerProperty())
+      {
+        if(0 == componentIndex)
+        {
+          mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 0> >::New(*targetProperty,
+                                                                                                                             propertyOwners,
+                                                                                                                             func,
+                                                                                                                             mRemoveAction);
+        }
+        else if(1 == componentIndex)
+        {
+          mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 1> >::New(*targetProperty,
+                                                                                                                             propertyOwners,
+                                                                                                                             func,
+                                                                                                                             mRemoveAction);
+        }
+        else if(2 == componentIndex)
+        {
+          mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 2> >::New(*targetProperty,
+                                                                                                                             propertyOwners,
+                                                                                                                             func,
+                                                                                                                             mRemoveAction);
+        }
+        // Do not create a resetter for transform manager property
+      }
+      else
+      {
+        if(0 == componentIndex)
+        {
+          mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
+        }
+        else if(1 == componentIndex)
+        {
+          mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
+        }
+        else if(2 == componentIndex)
+        {
+          mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorZ<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
+        }
+        resetterRequired = (mSceneGraphConstraint != nullptr);
+      }
+    }
+    else if(PropertyTypes::Get<Vector4>() == targetProperty->GetType())
+    {
+      // Constrain float component of Vector4 property
+      if(0 == componentIndex)
+      {
+        mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
+      }
+      else if(1 == componentIndex)
+      {
+        mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
+      }
+      else if(2 == componentIndex)
+      {
+        mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorZ<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
+      }
+      else if(3 == componentIndex)
+      {
+        mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorW<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
+      }
+
+      resetterRequired = (mSceneGraphConstraint != nullptr);
+    }
+  }
+
 protected:
   ConstraintFunctionPtr mUserFunction;
 };
index 617f592..75188ef 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -49,6 +49,26 @@ inline void AdjustProperty(Property::Value& currentPropertyValue, const Property
   }
 }
 
+/// Helper to convert and then assign the property value
+template<typename PropertyType, typename Value>
+inline void SetValue(const Property::Value& propertyValue, Value& value)
+{
+  PropertyType convertedValue;
+  if(propertyValue.Get(convertedValue))
+  {
+    value = convertedValue;
+  }
+}
+
+/// Helper to check container property type and set appropriately
+template<typename ContainerType>
+inline void SetContainerValue(const ContainerType* containerPtr, Property::Value& value)
+{
+  if(containerPtr)
+  {
+    value = *containerPtr;
+  }
+}
 } // unnamed namespace
 
 void PropertyMetadata::SetPropertyValue(const Property::Value& propertyValue)
@@ -63,111 +83,67 @@ void PropertyMetadata::SetPropertyValue(const Property::Value& propertyValue)
 
     case Property::RECTANGLE:
     {
-      Rect<int32_t> convertedValue;
-      if(propertyValue.Get(convertedValue))
-      {
-        value = convertedValue;
-      }
+      SetValue<Rect<int32_t>>(propertyValue, value);
       break;
     }
 
     case Property::STRING:
     {
-      std::string convertedValue;
-      if(propertyValue.Get(convertedValue))
-      {
-        value = convertedValue;
-      }
+      SetValue<std::string>(propertyValue, value);
       break;
     }
 
     case Property::ARRAY:
     {
-      const Property::Array* array = propertyValue.GetArray();
-      if(array)
-      {
-        value = *array;
-      }
+      SetContainerValue(propertyValue.GetArray(), value);
       break;
     }
 
     case Property::MAP:
     {
-      const Property::Map* map = propertyValue.GetMap();
-      if(map)
-      {
-        value = *map;
-      }
+      SetContainerValue(propertyValue.GetMap(), value);
       break;
     }
 
     case Property::EXTENTS:
     {
-      Extents convertedValue;
-      if(propertyValue.Get(convertedValue))
-      {
-        value = convertedValue;
-      }
+      SetValue<Extents>(propertyValue, value);
       break;
     }
 
     case Property::BOOLEAN:
     {
-      bool convertedValue;
-      if(propertyValue.Get(convertedValue))
-      {
-        value = convertedValue;
-      }
+      SetValue<bool>(propertyValue, value);
       break;
     }
 
     case Property::INTEGER:
     {
-      int32_t convertedValue;
-      if(propertyValue.Get(convertedValue))
-      {
-        value = convertedValue;
-      }
+      SetValue<int32_t>(propertyValue, value);
       break;
     }
 
     case Property::FLOAT:
     {
-      float convertedValue;
-      if(propertyValue.Get(convertedValue))
-      {
-        value = convertedValue;
-      }
+      SetValue<float>(propertyValue, value);
       break;
     }
 
     case Property::ROTATION:
     {
-      Quaternion convertedValue;
-      if(propertyValue.Get(convertedValue))
-      {
-        value = convertedValue;
-      }
+      SetValue<Quaternion>(propertyValue, value);
       break;
     }
 
     case Property::MATRIX:
     {
-      Matrix convertedValue;
-      if(propertyValue.Get(convertedValue))
-      {
-        value = convertedValue;
-      }
+      SetValue<Matrix>(propertyValue, value);
       break;
     }
 
     case Property::MATRIX3:
     {
-      Matrix3 convertedValue;
-      if(propertyValue.Get(convertedValue))
-      {
-        value = convertedValue;
-      }
+      SetValue<Matrix3>(propertyValue, value);
       break;
     }
 
@@ -176,17 +152,25 @@ void PropertyMetadata::SetPropertyValue(const Property::Value& propertyValue)
       Vector2 vector2Value;
       value.Get(vector2Value);
 
-      if(componentIndex == 0)
-      {
-        vector2Value.x = propertyValue.Get<float>();
-      }
-      else if(componentIndex == 1)
+      switch(componentIndex)
       {
-        vector2Value.y = propertyValue.Get<float>();
-      }
-      else
-      {
-        propertyValue.Get(vector2Value);
+        case 0:
+        {
+          SetValue<float>(propertyValue, vector2Value.x);
+          break;
+        }
+
+        case 1:
+        {
+          SetValue<float>(propertyValue, vector2Value.y);
+          break;
+        }
+
+        default:
+        {
+          SetValue<Vector2>(propertyValue, vector2Value);
+          break;
+        }
       }
 
       value = vector2Value;
@@ -198,21 +182,31 @@ void PropertyMetadata::SetPropertyValue(const Property::Value& propertyValue)
       Vector3 vector3Value;
       value.Get(vector3Value);
 
-      if(componentIndex == 0)
-      {
-        vector3Value.x = propertyValue.Get<float>();
-      }
-      else if(componentIndex == 1)
+      switch(componentIndex)
       {
-        vector3Value.y = propertyValue.Get<float>();
-      }
-      else if(componentIndex == 2)
-      {
-        vector3Value.z = propertyValue.Get<float>();
-      }
-      else
-      {
-        propertyValue.Get(vector3Value);
+        case 0:
+        {
+          SetValue<float>(propertyValue, vector3Value.x);
+          break;
+        }
+
+        case 1:
+        {
+          SetValue<float>(propertyValue, vector3Value.y);
+          break;
+        }
+
+        case 2:
+        {
+          SetValue<float>(propertyValue, vector3Value.z);
+          break;
+        }
+
+        default:
+        {
+          SetValue<Vector3>(propertyValue, vector3Value);
+          break;
+        }
       }
 
       value = vector3Value;
@@ -224,25 +218,37 @@ void PropertyMetadata::SetPropertyValue(const Property::Value& propertyValue)
       Vector4 vector4Value;
       value.Get(vector4Value);
 
-      if(componentIndex == 0)
-      {
-        vector4Value.x = propertyValue.Get<float>();
-      }
-      else if(componentIndex == 1)
+      switch(componentIndex)
       {
-        vector4Value.y = propertyValue.Get<float>();
-      }
-      else if(componentIndex == 2)
-      {
-        vector4Value.z = propertyValue.Get<float>();
-      }
-      else if(componentIndex == 3)
-      {
-        vector4Value.w = propertyValue.Get<float>();
-      }
-      else
-      {
-        propertyValue.Get(vector4Value);
+        case 0:
+        {
+          SetValue<float>(propertyValue, vector4Value.x);
+          break;
+        }
+
+        case 1:
+        {
+          SetValue<float>(propertyValue, vector4Value.y);
+          break;
+        }
+
+        case 2:
+        {
+          SetValue<float>(propertyValue, vector4Value.z);
+          break;
+        }
+
+        case 3:
+        {
+          SetValue<float>(propertyValue, vector4Value.w);
+          break;
+        }
+
+        default:
+        {
+          SetValue<Vector4>(propertyValue, vector4Value);
+          break;
+        }
       }
 
       value = vector4Value;
index e632717..6a589c1 100644 (file)
@@ -158,43 +158,23 @@ bool IsActorExclusiveToAnotherRenderTask(const Actor&
 }
 
 /**
- * Recursively hit test all the actors, without crossing into other layers.
- * This algorithm performs a Depth-First-Search (DFS) on all Actors within Layer.
- * Hit-Testing each Actor, noting the distance from the Ray-Origin (3D origin
- * of touch vector). The closest Hit-Tested Actor is that which is returned.
- * Exceptions to this rule are:
- * - When comparing against renderable parents, if Actor is the same distance
- * or closer than it's renderable parent, then it takes priority.
+ * Hit tests the given actor and updates the in/out variables appropriately
  */
-HitActor HitTestWithinLayer(Actor&                                     actor,
-                            const RenderTask&                          renderTask,
-                            const RenderTaskList::ExclusivesContainer& exclusives,
-                            const Vector4&                             rayOrigin,
-                            const Vector4&                             rayDir,
-                            const float&                               nearClippingPlane,
-                            const float&                               farClippingPlane,
-                            HitTestInterface&                          hitCheck,
-                            const bool&                                overlayed,
-                            bool&                                      overlayHit,
-                            bool                                       layerIs3d,
-                            const RayTest&                             rayTest,
-                            const Integration::Point&                  point,
-                            const uint32_t                             eventTime)
+void HitTestActor(const RenderTask&         renderTask,
+                  const Vector4&            rayOrigin,
+                  const Vector4&            rayDir,
+                  const float&              nearClippingPlane,
+                  const float&              farClippingPlane,
+                  HitTestInterface&         hitCheck,
+                  const RayTest&            rayTest,
+                  const Integration::Point& point,
+                  const uint32_t            eventTime,
+                  bool                      clippingActor,
+                  bool                      overlayedActor,
+                  Actor&                    actor,
+                  bool&                     overlayHit,
+                  HitActor&                 hit)
 {
-  HitActor hit;
-
-  if(IsActorExclusiveToAnotherRenderTask(actor, renderTask, exclusives))
-  {
-    return hit;
-  }
-
-  // For clipping, regardless of whether we have hit this actor or not.
-  // This is used later to ensure all nested clipped children have hit
-  // all clipping actors also for them to be counted as hit.
-  bool clippingActor  = actor.GetClippingMode() != ClippingMode::DISABLED;
-  bool overlayedActor = overlayed || actor.IsOverlay();
-
-  // If we are a clipping actor or hittable...
   if(clippingActor || hitCheck.IsActorHittable(&actor))
   {
     Vector3 size(actor.GetCurrentSize());
@@ -256,6 +236,76 @@ HitActor HitTestWithinLayer(Actor&                                     actor,
       }
     }
   }
+}
+
+/**
+ * When iterating through the children of an actor, this method updates the child-hit-data.
+ */
+void UpdateChildHitData(const HitActor& hit, const HitActor& currentHit, const bool layerIs3d, const bool parentIsRenderable, HitActor& childHit)
+{
+  bool updateChildHit = false;
+  if(currentHit.distance >= 0.0f)
+  {
+    if(layerIs3d)
+    {
+      updateChildHit = ((currentHit.depth > childHit.depth) ||
+                        ((currentHit.depth == childHit.depth) && (currentHit.distance < childHit.distance)));
+    }
+    else
+    {
+      updateChildHit = currentHit.depth >= childHit.depth;
+    }
+  }
+
+  if(updateChildHit)
+  {
+    if(!parentIsRenderable || currentHit.depth > hit.depth ||
+       (layerIs3d && (currentHit.depth == hit.depth && currentHit.distance < hit.distance)))
+    {
+      childHit = currentHit;
+    }
+  }
+}
+
+/**
+ * Recursively hit test all the actors, without crossing into other layers.
+ * This algorithm performs a Depth-First-Search (DFS) on all Actors within Layer.
+ * Hit-Testing each Actor, noting the distance from the Ray-Origin (3D origin
+ * of touch vector). The closest Hit-Tested Actor is that which is returned.
+ * Exceptions to this rule are:
+ * - When comparing against renderable parents, if Actor is the same distance
+ * or closer than it's renderable parent, then it takes priority.
+ */
+HitActor HitTestWithinLayer(Actor&                                     actor,
+                            const RenderTask&                          renderTask,
+                            const RenderTaskList::ExclusivesContainer& exclusives,
+                            const Vector4&                             rayOrigin,
+                            const Vector4&                             rayDir,
+                            const float&                               nearClippingPlane,
+                            const float&                               farClippingPlane,
+                            HitTestInterface&                          hitCheck,
+                            const bool&                                overlayed,
+                            bool&                                      overlayHit,
+                            bool                                       layerIs3d,
+                            const RayTest&                             rayTest,
+                            const Integration::Point&                  point,
+                            const uint32_t                             eventTime)
+{
+  HitActor hit;
+
+  if(IsActorExclusiveToAnotherRenderTask(actor, renderTask, exclusives))
+  {
+    return hit;
+  }
+
+  // For clipping, regardless of whether we have hit this actor or not.
+  // This is used later to ensure all nested clipped children have hit
+  // all clipping actors also for them to be counted as hit.
+  bool clippingActor  = actor.GetClippingMode() != ClippingMode::DISABLED;
+  bool overlayedActor = overlayed || actor.IsOverlay();
+
+  // If we are a clipping actor or hittable...
+  HitTestActor(renderTask, rayOrigin, rayDir, nearClippingPlane, farClippingPlane, hitCheck, rayTest, point, eventTime, clippingActor, overlayedActor, actor, overlayHit, hit);
 
   // If current actor is clipping, and hit failed, We should not checkup child actors. Fast return
   if(clippingActor && !(hit.actor))
@@ -303,28 +353,7 @@ HitActor HitTestWithinLayer(Actor&                                     actor,
           continue;
         }
 
-        bool updateChildHit = false;
-        if(currentHit.distance >= 0.0f)
-        {
-          if(layerIs3d)
-          {
-            updateChildHit = ((currentHit.depth > childHit.depth) ||
-                              ((currentHit.depth == childHit.depth) && (currentHit.distance < childHit.distance)));
-          }
-          else
-          {
-            updateChildHit = currentHit.depth >= childHit.depth;
-          }
-        }
-
-        if(updateChildHit)
-        {
-          if(!parentIsRenderable || currentHit.depth > hit.depth ||
-             (layerIs3d && (currentHit.depth == hit.depth && currentHit.distance < hit.distance)))
-          {
-            childHit = currentHit;
-          }
-        }
+        UpdateChildHitData(hit, currentHit, layerIs3d, parentIsRenderable, childHit);
       }
     }
   }
index 3808a54..2bf82f1 100644 (file)
@@ -52,6 +52,23 @@ BaseHandle Create()
 
 TypeRegistration mType(typeid(Dali::DecoratedVisualRenderer), typeid(Dali::VisualRenderer), Create, DecoratedVisualRendererDefaultProperties);
 
+/**
+ * Sets both the cached value of a property and sends a message to set the animatable property in the Update thread.
+ * @tparam T The property type
+ * @param eventThreadServices The event thread services
+ * @param propertyValue The new property value given
+ * @param cachedValue The local cached value of the property
+ * @param animatableProperty The animatable property to set on the update-thread
+ */
+template<typename T>
+void SetValue(EventThreadServices& eventThreadServices, const Property::Value& propertyValue, T& cachedValue, const SceneGraph::AnimatableProperty<T>& animatableProperty)
+{
+  if(propertyValue.Get(cachedValue))
+  {
+    BakeMessage<T>(eventThreadServices, animatableProperty, cachedValue);
+  }
+}
+
 } // unnamed namespace
 
 DecoratedVisualRendererPtr DecoratedVisualRenderer::New()
@@ -90,10 +107,7 @@ DecoratedVisualRenderer::DecoratedVisualRenderer(const SceneGraph::Renderer* sce
 {
 }
 
-DecoratedVisualRenderer::~DecoratedVisualRenderer()
-{
-  // The scene object will be deleted by ~VisualRenderer
-}
+DecoratedVisualRenderer::~DecoratedVisualRenderer() = default; // The scene object will be deleted by ~VisualRenderer
 
 void DecoratedVisualRenderer::SetDefaultProperty(Property::Index        index,
                                                  const Property::Value& propertyValue)
@@ -104,120 +118,55 @@ void DecoratedVisualRenderer::SetDefaultProperty(Property::Index        index,
   }
   else
   {
-    switch(index)
+    const SceneGraph::Renderer& sceneObject = GetVisualRendererSceneObject();
+    auto visualProperties = sceneObject.GetVisualProperties();
+
+    if(visualProperties)
     {
-      case Dali::DecoratedVisualRenderer::Property::CORNER_RADIUS:
+      auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
+
+      if(decoratedVisualProperties)
       {
-        if(propertyValue.Get(mDecoratedPropertyCache.mCornerRadius))
-        {
-          const SceneGraph::Renderer& sceneObject      = GetVisualRendererSceneObject();
-          auto                        visualProperties = sceneObject.GetVisualProperties();
+        EventThreadServices& eventThreadServices = GetEventThreadServices();
 
-          if(visualProperties)
+        switch(index)
+        {
+          case Dali::DecoratedVisualRenderer::Property::CORNER_RADIUS:
           {
-            auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
-            if(decoratedVisualProperties)
-            {
-              BakeMessage<Vector4>(GetEventThreadServices(), decoratedVisualProperties->mCornerRadius, mDecoratedPropertyCache.mCornerRadius);
-            }
+            SetValue(eventThreadServices, propertyValue, mDecoratedPropertyCache.mCornerRadius, decoratedVisualProperties->mCornerRadius);
+            break;
           }
-        }
-        break;
-      }
-
-      case Dali::DecoratedVisualRenderer::Property::CORNER_RADIUS_POLICY:
-      {
-        if(propertyValue.Get(mDecoratedPropertyCache.mCornerRadiusPolicy))
-        {
-          const SceneGraph::Renderer& sceneObject      = GetVisualRendererSceneObject();
-          auto                        visualProperties = sceneObject.GetVisualProperties();
 
-          if(visualProperties)
+          case Dali::DecoratedVisualRenderer::Property::CORNER_RADIUS_POLICY:
           {
-            auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
-            if(decoratedVisualProperties)
-            {
-              BakeMessage<float>(GetEventThreadServices(), decoratedVisualProperties->mCornerRadiusPolicy, mDecoratedPropertyCache.mCornerRadiusPolicy);
-            }
+            SetValue(eventThreadServices, propertyValue, mDecoratedPropertyCache.mCornerRadiusPolicy, decoratedVisualProperties->mCornerRadiusPolicy);
+            break;
           }
-        }
-        break;
-      }
-
-      case Dali::DecoratedVisualRenderer::Property::BORDERLINE_WIDTH:
-      {
-        if(propertyValue.Get(mDecoratedPropertyCache.mBorderlineWidth))
-        {
-          const SceneGraph::Renderer& sceneObject      = GetVisualRendererSceneObject();
-          auto                        visualProperties = sceneObject.GetVisualProperties();
 
-          if(visualProperties)
+          case Dali::DecoratedVisualRenderer::Property::BORDERLINE_WIDTH:
           {
-            auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
-            if(decoratedVisualProperties)
-            {
-              BakeMessage<float>(GetEventThreadServices(), decoratedVisualProperties->mBorderlineWidth, mDecoratedPropertyCache.mBorderlineWidth);
-            }
+            SetValue(eventThreadServices, propertyValue, mDecoratedPropertyCache.mBorderlineWidth, decoratedVisualProperties->mBorderlineWidth);
+            break;
           }
-        }
-        break;
-      }
-
-      case Dali::DecoratedVisualRenderer::Property::BORDERLINE_COLOR:
-      {
-        if(propertyValue.Get(mDecoratedPropertyCache.mBorderlineColor))
-        {
-          const SceneGraph::Renderer& sceneObject      = GetVisualRendererSceneObject();
-          auto                        visualProperties = sceneObject.GetVisualProperties();
 
-          if(visualProperties)
+          case Dali::DecoratedVisualRenderer::Property::BORDERLINE_COLOR:
           {
-            auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
-            if(decoratedVisualProperties)
-            {
-              BakeMessage<Vector4>(GetEventThreadServices(), decoratedVisualProperties->mBorderlineColor, mDecoratedPropertyCache.mBorderlineColor);
-            }
+            SetValue(eventThreadServices, propertyValue,mDecoratedPropertyCache.mBorderlineColor, decoratedVisualProperties->mBorderlineColor);
+            break;
           }
-        }
-        break;
-      }
 
-      case Dali::DecoratedVisualRenderer::Property::BORDERLINE_OFFSET:
-      {
-        if(propertyValue.Get(mDecoratedPropertyCache.mBorderlineOffset))
-        {
-          const SceneGraph::Renderer& sceneObject      = GetVisualRendererSceneObject();
-          auto                        visualProperties = sceneObject.GetVisualProperties();
-
-          if(visualProperties)
+          case Dali::DecoratedVisualRenderer::Property::BORDERLINE_OFFSET:
           {
-            auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
-            if(decoratedVisualProperties)
-            {
-              BakeMessage<float>(GetEventThreadServices(), decoratedVisualProperties->mBorderlineOffset, mDecoratedPropertyCache.mBorderlineOffset);
-            }
+            SetValue(eventThreadServices, propertyValue,mDecoratedPropertyCache.mBorderlineOffset, decoratedVisualProperties->mBorderlineOffset);
+            break;
           }
-        }
-        break;
-      }
-
-      case Dali::DecoratedVisualRenderer::Property::BLUR_RADIUS:
-      {
-        if(propertyValue.Get(mDecoratedPropertyCache.mBlurRadius))
-        {
-          const SceneGraph::Renderer& sceneObject      = GetVisualRendererSceneObject();
-          auto                        visualProperties = sceneObject.GetVisualProperties();
 
-          if(visualProperties)
+          case Dali::DecoratedVisualRenderer::Property::BLUR_RADIUS:
           {
-            auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
-            if(decoratedVisualProperties)
-            {
-              BakeMessage<float>(GetEventThreadServices(), decoratedVisualProperties->mBlurRadius, mDecoratedPropertyCache.mBlurRadius);
-            }
+            SetValue(eventThreadServices, propertyValue,mDecoratedPropertyCache.mBlurRadius, decoratedVisualProperties->mBlurRadius);
+            break;
           }
         }
-        break;
       }
     }
   }
index b6c5cc9..d386150 100644 (file)
@@ -100,7 +100,7 @@ Texture::~Texture()
 
 bool Texture::Upload(PixelDataPtr pixelData)
 {
-  return Upload(pixelData, 0u, 0u, 0u, 0u, pixelData->GetWidth(), pixelData->GetHeight());
+  return UploadSubPixelData(pixelData, 0u, 0u, pixelData->GetWidth(), pixelData->GetHeight(), 0u, 0u, 0u, 0u, pixelData->GetWidth(), pixelData->GetHeight());
 }
 
 bool Texture::Upload(PixelDataPtr pixelData,
@@ -111,6 +111,30 @@ bool Texture::Upload(PixelDataPtr pixelData,
                      uint32_t     width,
                      uint32_t     height)
 {
+  return UploadSubPixelData(pixelData, 0u, 0u, pixelData->GetWidth(), pixelData->GetHeight(), layer, mipmap, xOffset, yOffset, width, height);
+}
+
+bool Texture::UploadSubPixelData(PixelDataPtr pixelData,
+                                 uint32_t     dataXOffset,
+                                 uint32_t     dataYOffset,
+                                 uint32_t     dataWidth,
+                                 uint32_t     dataHeight)
+{
+  return UploadSubPixelData(pixelData, dataXOffset, dataYOffset, dataWidth, dataHeight, 0u, 0u, 0u, 0u, dataWidth, dataHeight);
+}
+
+bool Texture::UploadSubPixelData(PixelDataPtr pixelData,
+                                 uint32_t     dataXOffset,
+                                 uint32_t     dataYOffset,
+                                 uint32_t     dataWidth,
+                                 uint32_t     dataHeight,
+                                 uint32_t     layer,
+                                 uint32_t     mipmap,
+                                 uint32_t     xOffset,
+                                 uint32_t     yOffset,
+                                 uint32_t     width,
+                                 uint32_t     height)
+{
   constexpr auto max_value = std::numeric_limits<uint16_t>::max();
   DALI_ASSERT_ALWAYS(layer < max_value &&
                      mipmap < max_value &&
@@ -118,6 +142,8 @@ bool Texture::Upload(PixelDataPtr pixelData,
                      yOffset < max_value &&
                      width < max_value &&
                      height < max_value &&
+                     dataWidth < max_value &&
+                     dataHeight < max_value &&
                      "Parameter value out of range");
 
   bool result(false);
@@ -129,7 +155,7 @@ bool Texture::Upload(PixelDataPtr pixelData,
     }
     else
     {
-      uint32_t pixelDataSize = pixelData->GetWidth() * pixelData->GetHeight();
+      uint32_t pixelDataSize = dataWidth * dataHeight;
       if(pixelData->GetBuffer() == nullptr || pixelDataSize == 0)
       {
         DALI_LOG_ERROR("PixelData is empty\n");
@@ -143,6 +169,19 @@ bool Texture::Upload(PixelDataPtr pixelData,
           {
             DALI_LOG_ERROR("PixelData of an incorrect size when trying to update texture\n");
           }
+          else if(Pixel::IsCompressed(mFormat) &&
+                  ((dataXOffset != 0) ||
+                   (dataYOffset != 0) ||
+                   (dataWidth != pixelData->GetWidth()) ||
+                   (dataHeight != pixelData->GetHeight())))
+          {
+            DALI_LOG_ERROR("Compressed pixel format don't support SubPixelData upload\n");
+          }
+          else if((dataXOffset + dataWidth > pixelData->GetWidth()) ||
+                  (dataYOffset + dataHeight > pixelData->GetHeight()))
+          {
+            DALI_LOG_ERROR("PixelData of an incorrect subsize when trying to update texture\n");
+          }
           else if((xOffset + width > (mSize.GetWidth() / (1u << mipmap))) ||
                   (yOffset + height > (mSize.GetHeight() / (1u << mipmap))))
           {
@@ -151,7 +190,11 @@ bool Texture::Upload(PixelDataPtr pixelData,
           else
           {
             //Parameters are correct. Send message to upload data to the texture
-            UploadParams params = {static_cast<uint16_t>(layer),
+            UploadParams params = {static_cast<uint32_t>(dataXOffset),
+                                   static_cast<uint32_t>(dataYOffset),
+                                   static_cast<uint16_t>(dataWidth),
+                                   static_cast<uint16_t>(dataHeight),
+                                   static_cast<uint16_t>(layer),
                                    static_cast<uint16_t>(mipmap),
                                    static_cast<uint16_t>(xOffset),
                                    static_cast<uint16_t>(yOffset),
index 84faac6..c00e663 100644 (file)
@@ -48,12 +48,16 @@ public:
    */
   struct UploadParams
   {
-    uint16_t layer;   ///< Specifies the layer of a cube map or array texture
-    uint16_t mipmap;  ///< Specifies the level-of-detail number. Level 0 is the base image level. Level n is the nth mipmap reduction image.
-    uint16_t xOffset; ///< Specifies a texel offset in the x direction within the texture array.
-    uint16_t yOffset; ///< Specifies a texel offset in the y direction within the texture array.
-    uint16_t width;   ///< Specifies the width of the texture subimage
-    uint16_t height;  ///< Specifies the height of the texture subimage.
+    uint32_t dataXOffset; ///< Specifies a pixeldata offset in the x direction within the pixeldata buffer.
+    uint32_t dataYOffset; ///< Specifies a pixeldata offset in the y direction within the pixeldata buffer.
+    uint16_t dataWidth;   ///< Specifies the width of the pixeldata subimage.
+    uint16_t dataHeight;  ///< Specifies the height of the pixeldata subimage.
+    uint16_t layer;       ///< Specifies the layer of a cube map or array texture
+    uint16_t mipmap;      ///< Specifies the level-of-detail number. Level 0 is the base image level. Level n is the nth mipmap reduction image.
+    uint16_t xOffset;     ///< Specifies a texel offset in the x direction within the texture array.
+    uint16_t yOffset;     ///< Specifies a texel offset in the y direction within the texture array.
+    uint16_t width;       ///< Specifies the width of the texture subimage
+    uint16_t height;      ///< Specifies the height of the texture subimage.
   };
 
   /**
@@ -98,6 +102,30 @@ public:
               uint32_t     height);
 
   /**
+   * @copydoc Dali::Texture::UploadSubPixelData()
+   */
+  bool UploadSubPixelData(PixelDataPtr pixelData,
+                          uint32_t     dataXOffset,
+                          uint32_t     dataYOffset,
+                          uint32_t     dataWidth,
+                          uint32_t     dataHeight);
+
+  /**
+   * @copydoc Dali::Texture::UploadSubPixelData()
+   */
+  bool UploadSubPixelData(PixelDataPtr pixelData,
+                          uint32_t     dataXOffset,
+                          uint32_t     dataYOffset,
+                          uint32_t     dataWidth,
+                          uint32_t     dataHeight,
+                          uint32_t     layer,
+                          uint32_t     mipmap,
+                          uint32_t     xOffset,
+                          uint32_t     yOffset,
+                          uint32_t     width,
+                          uint32_t     height);
+
+  /**
    * @copydoc Dali::Texture::GenerateMipmaps()
    */
   void GenerateMipmaps();
index b0fca79..f2bc5a3 100644 (file)
@@ -286,15 +286,58 @@ void Texture::Upload(PixelDataPtr pixelData, const Internal::Texture::UploadPara
   }
 
   Graphics::TextureUpdateInfo info{};
+
+  const uint32_t bytePerPixel = Pixel::GetBytesPerPixel(pixelData->GetPixelFormat());
+  const uint32_t srcStride    = pixelData->GetStride();
+  uint32_t       srcOffset    = 0u;
+  uint32_t       srcSize      = pixelData->GetBufferSize();
+
+  const bool requiredSubPixelData = (!Pixel::IsCompressed(pixelData->GetPixelFormat())) &&
+                                    ((params.dataXOffset != 0) ||
+                                     (params.dataYOffset != 0) ||
+                                     (params.dataWidth != pixelData->GetWidth()) ||
+                                     (params.dataHeight != pixelData->GetHeight()));
+
+  if(requiredSubPixelData)
+  {
+    /**
+     * TextureUpdateInfo use byte scaled offset / size.
+     *
+     * To make we only use sub-data of inputed PixelData, make srcOffset as 'start of SubPixelData.
+     *
+     *   |---- dataStrideByte -----|
+     *   |-----| <-- dataXOffsetByte
+     *   ...........................
+     *   ......A-----------+........
+     *   ......|           |........
+     *   ......|           |........
+     *   ......+-----------+C.......
+     *   ......B....................
+     *
+     * A) Start of SubPixelData. offsetByte = dataStrideByte * dataYOffset + dataXOffsetByte.
+     * B) offsetByte = A).offsetByte + dataStrideByte * dataHeight. Note, It can be out of original PixelData boundary.
+     * C) End of SubPixelData. offsetByte = B).offsetByte - dataStrideByte + dataWidthByte.
+     *
+     * srcOffset = A).offsetByte;
+     * srcSize = ( C).offsetByte - A).offsetByte );
+     */
+    const uint32_t dataStrideByte  = (srcStride ? srcStride : static_cast<uint32_t>(params.dataWidth)) * bytePerPixel;
+    const uint32_t dataXOffsetByte = params.dataXOffset * bytePerPixel;
+    const uint32_t dataWidthByte   = static_cast<uint32_t>(params.dataWidth) * bytePerPixel;
+
+    srcOffset = params.dataYOffset * dataStrideByte + dataXOffsetByte;
+    srcSize   = static_cast<uint32_t>(params.dataHeight) * dataStrideByte - (dataStrideByte - dataWidthByte);
+  }
+
   info.dstTexture   = mGraphicsTexture.get();
   info.dstOffset2D  = {params.xOffset, params.yOffset};
   info.layer        = params.layer;
   info.level        = params.mipmap;
   info.srcReference = 0;
-  info.srcExtent2D  = {params.width, params.height};
-  info.srcOffset    = 0;
-  info.srcSize      = pixelData->GetBufferSize();
-  info.srcStride    = pixelData->GetStride();
+  info.srcExtent2D  = {params.dataWidth, params.dataHeight};
+  info.srcOffset    = srcOffset;
+  info.srcSize      = srcSize;
+  info.srcStride    = srcStride;
   info.srcFormat    = ConvertPixelFormat(pixelData->GetPixelFormat());
 
   Graphics::TextureUpdateSourceInfo updateSourceInfo{};
index 744d674..67b47a5 100644 (file)
@@ -268,6 +268,7 @@ inline void AddRendererToRenderList(BufferIndex         updateBufferIndex,
 
       if(DALI_LIKELY(renderable.mRenderer))
       {
+        partialRenderingCacheInfo.color.a *= renderable.mRenderer->GetOpacity(updateBufferIndex);
         partialRenderingCacheInfo.textureSet = renderable.mRenderer->GetTextureSet();
       }
 
index 69a55a0..4c3a96d 100644 (file)
@@ -27,7 +27,7 @@ namespace Dali
 {
 const uint32_t    CORE_MAJOR_VERSION = 2;
 const uint32_t    CORE_MINOR_VERSION = 1;
-const uint32_t    CORE_MICRO_VERSION = 31;
+const uint32_t    CORE_MICRO_VERSION = 32;
 const char* const CORE_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index 90985a4..0dee73a 100644 (file)
 
 namespace Dali
 {
+bool Pixel::IsCompressed(Format pixelformat)
+{
+  switch(pixelformat)
+  {
+    case COMPRESSED_R11_EAC:
+    case COMPRESSED_SIGNED_R11_EAC:
+    case COMPRESSED_RG11_EAC:
+    case COMPRESSED_SIGNED_RG11_EAC:
+    case COMPRESSED_RGB8_ETC2:
+    case COMPRESSED_SRGB8_ETC2:
+    case COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+    case COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+    case COMPRESSED_RGBA8_ETC2_EAC:
+    case COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+    case COMPRESSED_RGB8_ETC1:
+    case COMPRESSED_RGB_PVRTC_4BPPV1:
+    case COMPRESSED_RGBA_ASTC_4x4_KHR:
+    case COMPRESSED_RGBA_ASTC_5x4_KHR:
+    case COMPRESSED_RGBA_ASTC_5x5_KHR:
+    case COMPRESSED_RGBA_ASTC_6x5_KHR:
+    case COMPRESSED_RGBA_ASTC_6x6_KHR:
+    case COMPRESSED_RGBA_ASTC_8x5_KHR:
+    case COMPRESSED_RGBA_ASTC_8x6_KHR:
+    case COMPRESSED_RGBA_ASTC_8x8_KHR:
+    case COMPRESSED_RGBA_ASTC_10x5_KHR:
+    case COMPRESSED_RGBA_ASTC_10x6_KHR:
+    case COMPRESSED_RGBA_ASTC_10x8_KHR:
+    case COMPRESSED_RGBA_ASTC_10x10_KHR:
+    case COMPRESSED_RGBA_ASTC_12x10_KHR:
+    case COMPRESSED_RGBA_ASTC_12x12_KHR:
+    case COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
+    case COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
+    case COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
+    case COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
+    case COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
+    case COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
+    case COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
+    case COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
+    case COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
+    case COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
+    case COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
+    case COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+    case COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
+    case COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
+    {
+      return true;
+    }
+    case INVALID:
+    case A8:
+    case L8:
+    case LA88:
+    case RGB565:
+    case BGR565:
+    case RGBA4444:
+    case BGRA4444:
+    case RGBA5551:
+    case BGRA5551:
+    case RGB888:
+    case RGB8888:
+    case BGR8888:
+    case RGBA8888:
+    case BGRA8888:
+    case RGB16F:
+    case RGB32F:
+    case DEPTH_UNSIGNED_INT:
+    case DEPTH_FLOAT:
+    case DEPTH_STENCIL:
+    case R11G11B10F:
+    case CHROMINANCE_U:
+    case CHROMINANCE_V:
+    {
+      return false;
+    }
+  }
+  return false;
+}
+
 bool Pixel::HasAlpha(Format pixelformat)
 {
   switch(pixelformat)
index d62907d..ff07691 100644 (file)
@@ -141,6 +141,15 @@ const Format FIRST_VALID_PIXEL_FORMAT = A8;
 const Format LAST_VALID_PIXEL_FORMAT = CHROMINANCE_V;
 
 /**
+ * @brief Whether specified pixel format is compressed or not.
+ *
+ * @SINCE_2_1.33
+ * @param[in] pixelFormat The pixel format
+ * @return True if pixel format is compressed type. False otherwise.
+ */
+DALI_CORE_API bool IsCompressed(Format pixelFormat);
+
+/**
  * @brief Whether specified pixel format contains an alpha value.
  *
  * @SINCE_1_0.0
index 902e290..327db18 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali2
 Summary:    DALi 3D Engine
-Version:    2.1.31
+Version:    2.1.32
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT