Merge "Add BuildPickingRay to devel api" into devel/master
[platform/core/uifw/dali-core.git] / automated-tests / src / dali / utc-Dali-Renderer.cpp
index 8557d2c..763fa67 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -2818,6 +2818,63 @@ int UtcDaliRendererSetDepthWriteMode(void)
   END_TEST;
 }
 
+int UtcDaliRendererBlendModeUseActorOpacity(void)
+{
+  TestApplication application;
+  tet_infoline("Test setting the UseActorOpacity");
+
+  Geometry geometry = CreateQuadGeometry();
+  Shader   shader   = CreateShader();
+  Renderer renderer = Renderer::New(geometry, shader);
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
+  Integration::Scene scene = application.GetScene();
+  scene.GetRootLayer().SetProperty(Layer::Property::BEHAVIOR, Layer::LAYER_3D);
+  scene.Add(actor);
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  renderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::USE_ACTOR_OPACITY);
+  actor.AddRenderer(renderer);
+  application.GetScene().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+
+  // Check the default depth-write status first.
+  DALI_TEST_CHECK(glAbstraction.GetLastDepthMask());
+
+  // Turn off depth-writing.
+  actor.SetProperty(Dali::Actor::Property::COLOR, Vector4(1, 1, 1, 0.5));
+
+  application.SendNotification();
+  application.Render();
+
+  // Check depth-write is now disabled.
+  DALI_TEST_CHECK(!glAbstraction.GetLastDepthMask());
+
+  // Turn on depth-writing.
+  actor.SetProperty(Dali::Actor::Property::COLOR, Vector4(1, 1, 1, 1));
+
+  application.SendNotification();
+  application.Render();
+
+  // Check depth-write is now enabled.
+  DALI_TEST_CHECK(glAbstraction.GetLastDepthMask());
+
+  // Turn off depth-writing.
+  actor.SetProperty(Dali::Actor::Property::COLOR, Vector4(1, 1, 1, 0.0));
+
+  application.SendNotification();
+  application.Render();
+
+  // if actor alpha is 0, SetDepthWriteEnable is not called so GetLastDepthMask returns default value true;
+  DALI_TEST_CHECK(glAbstraction.GetLastDepthMask());
+
+  END_TEST;
+}
+
 int UtcDaliRendererCheckStencilDefaults(void)
 {
   TestApplication application;
@@ -3521,6 +3578,85 @@ int UtcDaliRendererRegenerateUniformMap(void)
   END_TEST;
 }
 
+int UtcDaliRendererRenderAfterAddShader(void)
+{
+  TestApplication    application;
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+
+  tet_infoline("Test regenerating uniform map when shader changed");
+
+  Geometry geometry = CreateQuadGeometry();
+  Shader   shader1  = Shader::New("vertexSrc1", "fragmentSrc1");
+  Shader   shader2  = Shader::New("vertexSrc2", "fragmentSrc2");
+  Renderer renderer = Renderer::New(geometry, shader1);
+
+  // Register each shader1 and shader2 only had
+  shader1.RegisterProperty("uUniform1", Color::CRIMSON);
+  shader2.RegisterProperty("uShader2Only", Color::AQUA_MARINE);
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
+  actor.SetProperty(Actor::Property::COLOR, Vector4(1.0f, 0.0f, 1.0f, 1.0f));
+  application.GetScene().Add(actor);
+
+  Property::Value value = renderer.GetProperty(DevelRenderer::Property::RENDERING_BEHAVIOR);
+  int             renderingBehavior;
+  DALI_TEST_CHECK(value.Get(renderingBehavior));
+  DALI_TEST_EQUALS(static_cast<DevelRenderer::Rendering::Type>(renderingBehavior), DevelRenderer::Rendering::IF_REQUIRED, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render(0);
+
+  // Check uUniform1 rendered and uUniform2 not rendered before
+  Vector4 actualValue(Vector4::ZERO);
+  DALI_TEST_CHECK(glAbstraction.GetUniformValue<Vector4>("uUniform1", actualValue));
+  DALI_TEST_EQUALS(actualValue, Color::CRIMSON, TEST_LOCATION);
+
+  uint32_t updateStatus = application.GetUpdateStatus();
+
+  DALI_TEST_CHECK(!(updateStatus & Integration::KeepUpdating::STAGE_KEEP_RENDERING));
+
+  // Update for several frames
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+  drawTrace.Reset();
+
+  std::vector<UniformData> customUniforms{{"uShader2Only", Property::VECTOR4}};
+
+  application.GetGraphicsController().AddCustomUniforms(customUniforms);
+
+  // Change shader.
+  renderer.SetShader(shader2);
+
+  // Render and check the update status
+  application.SendNotification();
+  application.Render(0);
+
+  updateStatus = application.GetUpdateStatus();
+
+  DALI_TEST_CHECK(!(updateStatus & Integration::KeepUpdating::STAGE_KEEP_RENDERING));
+
+  DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 1, TEST_LOCATION);
+
+  // Check uUniform2 rendered now
+  DALI_TEST_CHECK(glAbstraction.GetUniformValue<Vector4>("uShader2Only", actualValue));
+  DALI_TEST_EQUALS(actualValue, Color::AQUA_MARINE, TEST_LOCATION);
+
+  END_TEST;
+}
+
 int UtcDaliRendererAddDrawCommands(void)
 {
   TestApplication application;
@@ -3787,3 +3923,335 @@ int UtcDaliRendererPreparePipeline(void)
 
   END_TEST;
 }
+
+int UtcDaliRendererUniformArrayOfStruct(void)
+{
+  TestApplication application;
+  tet_infoline("Test that uniforms that are elements of arrays of structs can be accessed");
+
+  std::vector<UniformData> customUniforms{{"arrayof[10].color", Property::VECTOR4},
+                                          {"arrayof[10].position", Property::VECTOR2},
+                                          {"arrayof[10].normal", Property::VECTOR3}};
+
+  application.GetGraphicsController().AddCustomUniforms(customUniforms);
+
+  Geometry geometry = CreateQuadGeometry();
+  Shader   shader   = Shader::New("vertexSrc", "fragmentSrc");
+  Renderer renderer = Renderer::New(geometry, shader);
+  Actor    actor    = Actor::New();
+  actor.AddRenderer(renderer);
+  actor[Actor::Property::SIZE] = Vector2(120, 120);
+  application.GetScene().Add(actor);
+
+  // Define some properties to match the custom uniforms.
+  // Ensure they can be written & read back from the abstraction.
+
+  struct UniformIndexPair
+  {
+    Property::Index index;
+    std::string     name;
+    UniformIndexPair(Property::Index index, std::string name)
+    : index(index),
+      name(name)
+    {
+    }
+  };
+  std::vector<UniformIndexPair> uniformIndices;
+
+  std::ostringstream oss;
+  for(int i = 0; i < 10; ++i)
+  {
+    Property::Index index;
+    oss << "arrayof[" << i << "].color";
+    Vector4 color = Color::WHITE;
+    color.r       = 25.5f * i;
+    index         = renderer.RegisterProperty(oss.str(), color);
+    uniformIndices.emplace_back(index, oss.str());
+
+    oss.str("");
+    oss.clear();
+    oss << "arrayof[" << i << "].position";
+    Vector2 pos(i, 10 + i * 5);
+    index = renderer.RegisterProperty(oss.str(), pos);
+    uniformIndices.emplace_back(index, oss.str());
+
+    oss.str("");
+    oss.clear();
+    oss << "arrayof[" << i << "].normal";
+    Vector3 normal(i, i * 10, i * 100);
+    index = renderer.RegisterProperty(oss.str(), normal);
+    uniformIndices.emplace_back(index, oss.str());
+    oss.str("");
+    oss.clear();
+  }
+  auto&           gl        = application.GetGlAbstraction();
+  TraceCallStack& callStack = gl.GetSetUniformTrace();
+  gl.EnableSetUniformCallTrace(true);
+
+  application.SendNotification();
+  application.Render();
+
+  // Check that the uniforms match.
+  TraceCallStack::NamedParams params;
+  for(auto& uniformInfo : uniformIndices)
+  {
+    Property::Value value = renderer.GetProperty(uniformInfo.index);
+    switch(value.GetType())
+    {
+      case Property::VECTOR2:
+      {
+        DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniformInfo.name, params));
+        Vector2 setValue;
+        DALI_TEST_CHECK(gl.GetUniformValue<Vector2>(uniformInfo.name.c_str(), setValue));
+        DALI_TEST_EQUALS(value.Get<Vector2>(), setValue, 0.001f, TEST_LOCATION);
+        break;
+      }
+      case Property::VECTOR3:
+      {
+        DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniformInfo.name, params));
+        Vector3 setValue;
+        DALI_TEST_CHECK(gl.GetUniformValue<Vector3>(uniformInfo.name.c_str(), setValue));
+        DALI_TEST_EQUALS(value.Get<Vector3>(), setValue, 0.001f, TEST_LOCATION);
+        break;
+      }
+      case Property::VECTOR4:
+      {
+        DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniformInfo.name, params));
+        Vector4 setValue;
+        DALI_TEST_CHECK(gl.GetUniformValue<Vector4>(uniformInfo.name.c_str(), setValue));
+        DALI_TEST_EQUALS(value.Get<Vector4>(), setValue, 0.001f, TEST_LOCATION);
+        break;
+      }
+      default:
+        break;
+    }
+  }
+
+  // There is a hash in the property name's uniform map: check this in debugger
+  // There is a hash in the reflection. Check this in the debugger.
+
+  // Check that the reflection contains individual locs for each array entry's struct element
+  // and that it hashes the whole string
+
+  // Ensure that the property name's hash is also for the whole string.
+
+  END_TEST;
+}
+
+int utcDaliRendererPartialUpdateChangeUniform(void)
+{
+  TestApplication application(
+    TestApplication::DEFAULT_SURFACE_WIDTH,
+    TestApplication::DEFAULT_SURFACE_HEIGHT,
+    TestApplication::DEFAULT_HORIZONTAL_DPI,
+    TestApplication::DEFAULT_VERTICAL_DPI,
+    true,
+    true);
+
+  tet_infoline("Check the damaged rect with changing uniform");
+
+  const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams());
+
+  std::vector<Rect<int>> damagedRects;
+  Rect<int>              clippingRect;
+  application.SendNotification();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+
+  // First render pass, nothing to render, adaptor would just do swap buffer.
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  Shader   shader   = Shader::New("VertexSource", "FragmentSource");
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New(geometry, shader);
+
+  Property::Index colorIndex = renderer.RegisterProperty("uFadeColor", Color::WHITE);
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  actor.SetProperty(Actor::Property::POSITION, Vector3(16.0f, 16.0f, 0.0f));
+  actor.SetProperty(Actor::Property::SIZE, Vector3(16.0f, 16.0f, 0.0f));
+  actor.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+
+  // 1. Actor added, damaged rect is added size of actor
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  // Aligned by 16
+  clippingRect = Rect<int>(16, 768, 32, 32); // in screen coordinates
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  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);
+
+  // 2. Change the uniform value
+  renderer.SetProperty(colorIndex, Color::RED);
+  application.SendNotification();
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  // Aligned by 16
+  clippingRect = Rect<int>(16, 768, 32, 32); // in screen coordinates
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // 3. Change the uniform value and another property together
+  actor.SetProperty(Actor::Property::COLOR, Color::YELLOW);
+  renderer.SetProperty(colorIndex, Color::BLUE);
+  application.SendNotification();
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  // Aligned by 16
+  clippingRect = Rect<int>(16, 768, 32, 32); // in screen coordinates
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // 4. Change the uniform value only
+  renderer.SetProperty(colorIndex, Color::RED); // Set the previous value (#2)
+  application.SendNotification();
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  // Aligned by 16
+  clippingRect = Rect<int>(16, 768, 32, 32); // in screen coordinates
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int utcDaliRendererPartialUpdateAddRemoveRenderer(void)
+{
+  TestApplication application(
+    TestApplication::DEFAULT_SURFACE_WIDTH,
+    TestApplication::DEFAULT_SURFACE_HEIGHT,
+    TestApplication::DEFAULT_HORIZONTAL_DPI,
+    TestApplication::DEFAULT_VERTICAL_DPI,
+    true,
+    true);
+
+  tet_infoline("Check the damaged rect with adding / removing renderer");
+
+  const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams());
+
+  Shader   shader   = Shader::New("VertexSource", "FragmentSource");
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New(geometry, shader);
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  actor.SetProperty(Actor::Property::POSITION, Vector3(16.0f, 16.0f, 0.0f));
+  actor.SetProperty(Actor::Property::SIZE, Vector3(16.0f, 16.0f, 0.0f));
+  actor.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+
+  std::vector<Rect<int>> damagedRects;
+  Rect<int>              clippingRect;
+
+  // 1. Actor added, damaged rect is added size of actor
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  // Aligned by 16
+  clippingRect = Rect<int>(16, 768, 32, 32); // in screen coordinates
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  // 2. Remove renderer
+  actor.RemoveRenderer(renderer);
+  application.SendNotification();
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // 3. Change a property value of the Renderer
+  renderer.SetProperty(DevelRenderer::Property::OPACITY, 0.5f);
+  application.SendNotification();
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // 4. Add renderer again
+  actor.AddRenderer(renderer);
+  application.SendNotification();
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // 5. Remove renderer agin
+  actor.RemoveRenderer(renderer);
+  application.SendNotification();
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  END_TEST;
+}