Merge branch 'devel/master' into tizen
authorseungho baek <sbsh.baek@samsung.com>
Mon, 11 Dec 2023 05:58:37 +0000 (14:58 +0900)
committerseungho baek <sbsh.baek@samsung.com>
Mon, 11 Dec 2023 05:58:37 +0000 (14:58 +0900)
Change-Id: Ib82439c652ede640bc1b9b3826260a9df5f331ad

18 files changed:
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-style-monitor.cpp
automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp
dali-physics/internal/bullet-impl/bullet-physics-debug-renderer.cpp
dali-physics/internal/chipmunk-impl/chipmunk-physics-debug-renderer.cpp
dali-toolkit/internal/file.list
dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp
dali-toolkit/internal/focus-manager/keyinput-focus-manager-impl.cpp
dali-toolkit/internal/graphics/shaders/image-visual-shader.frag
dali-toolkit/internal/graphics/shaders/image-visual-shader.vert
dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp
dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.cpp
dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.h
dali-toolkit/internal/visuals/image-visual-shader-debug.cpp [new file with mode: 0644]
dali-toolkit/internal/visuals/image-visual-shader-debug.h [new file with mode: 0644]
dali-toolkit/internal/visuals/image-visual-shader-factory.cpp
dali-toolkit/public-api/dali-toolkit-version.cpp
dali-toolkit/styles/debug-image-visual-shader-script.json [new file with mode: 0644]
packaging/dali-toolkit.spec

index 18c086f..e0000ec 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 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.
@@ -26,7 +26,7 @@
 
 namespace
 {
-const char* DEFAULT_THEME=
+const char* DEFAULT_THEME =
   "{\n"
   "  \"config\":\n"
   "  {\n"
@@ -44,22 +44,37 @@ const char* DEFAULT_THEME=
 
 struct NamedTheme
 {
-  NamedTheme( const std::string& name, const std::string& theme )
-  : name(name), theme(theme)
+  NamedTheme(const std::string& name, const std::string& theme)
+  : name(name),
+    theme(theme)
   {
   }
 
   std::string name;
   std::string theme;
 };
-typedef std::vector< NamedTheme > NamedThemes;
-NamedThemes gThemes;
+typedef std::vector<NamedTheme> NamedThemes;
+NamedThemes                     gThemes;
 
 std::string gTheme;
 std::string gFontFamily("LucidaSans");
 std::string gFontStyle("Regular");
 int         gFontSize(1);
-}
+
+constexpr std::string_view THROW_EXCEPTION_STYLE_FILE_NAME = "throwException";
+class DummyException : public std::exception
+{
+public:
+  DummyException()
+  {
+  }
+
+  const char* what() const throw()
+  {
+    return "DummyException";
+  }
+};
+} // namespace
 
 namespace Dali
 {
@@ -78,12 +93,12 @@ public: // Creation & Destruction
   ~StyleMonitor();
 
 public: // Style Information
-  std::string GetDefaultFontFamily() const;
-  std::string GetDefaultFontStyle() const;
-  float GetDefaultFontSize() const;
+  std::string        GetDefaultFontFamily() const;
+  std::string        GetDefaultFontStyle() const;
+  float              GetDefaultFontSize() const;
   const std::string& GetTheme() const;
-  void SetTheme(std::string theme);
-  bool LoadThemeFile( const std::string& filename, std::string& output );
+  void               SetTheme(std::string theme);
+  bool               LoadThemeFile(const std::string& filename, std::string& output);
 
 public: // Signals
   Dali::StyleMonitor::StyleChangeSignalType& StyleChangeSignal();
@@ -95,18 +110,18 @@ public: // Signals
 
 private:
   Dali::StyleMonitor::StyleChangeSignalType mStyleChangeSignal;
-  static Dali::StyleMonitor mToolkitStyleMonitor;
+  static Dali::StyleMonitor                 mToolkitStyleMonitor;
 
-  std::string mTheme;  ///<< Current theme name
+  std::string mTheme; ///<< Current theme name
 };
 
 Dali::StyleMonitor StyleMonitor::mToolkitStyleMonitor;
 
 Dali::StyleMonitor StyleMonitor::Get()
 {
-  if( ! mToolkitStyleMonitor )
+  if(!mToolkitStyleMonitor)
   {
-    mToolkitStyleMonitor = Dali::StyleMonitor( new Dali::Internal::Adaptor::StyleMonitor() );
+    mToolkitStyleMonitor = Dali::StyleMonitor(new Dali::Internal::Adaptor::StyleMonitor());
   }
   return mToolkitStyleMonitor;
 }
@@ -143,22 +158,27 @@ const std::string& StyleMonitor::GetTheme() const
 void StyleMonitor::SetTheme(std::string path)
 {
   mTheme = path;
-  EmitStyleChangeSignal( StyleChange::THEME_CHANGE );
+  EmitStyleChangeSignal(StyleChange::THEME_CHANGE);
 }
 
-bool StyleMonitor::LoadThemeFile( const std::string& filename, std::string& output )
+bool StyleMonitor::LoadThemeFile(const std::string& filename, std::string& output)
 {
-  for( NamedThemes::iterator iter = gThemes.begin(); iter != gThemes.end(); ++iter )
+  // Throw something exceptions during load file
+  if(filename == THROW_EXCEPTION_STYLE_FILE_NAME)
+  {
+    throw DummyException();
+  }
+  for(NamedThemes::iterator iter = gThemes.begin(); iter != gThemes.end(); ++iter)
   {
     NamedTheme& theme = *iter;
-    if( theme.name == filename )
+    if(theme.name == filename)
     {
       output = theme.theme;
       return true;
     }
   }
 
-  if( !gTheme.empty() )
+  if(!gTheme.empty())
   {
     output = gTheme;
   }
@@ -238,14 +258,14 @@ StyleMonitor::StyleChangeSignalType& StyleMonitor::StyleChangeSignal()
   return GetImplementation(*this).StyleChangeSignal();
 }
 
-bool StyleMonitor::LoadThemeFile( const std::string& filename, std::string& output )
+bool StyleMonitor::LoadThemeFile(const std::string& filename, std::string& output)
 {
   return GetImplementation(*this).LoadThemeFile(filename, output);
 }
 
 StyleMonitor& StyleMonitor::operator=(const StyleMonitor& monitor)
 {
-  if( *this != monitor )
+  if(*this != monitor)
   {
     BaseHandle::operator=(monitor);
   }
@@ -263,20 +283,19 @@ namespace Test
 {
 namespace StyleMonitor
 {
-
-void SetThemeFileOutput( const std::string& name, const std::string& output )
+void SetThemeFileOutput(const std::string& name, const std::string& output)
 {
-  for( NamedThemes::iterator iter = gThemes.begin(); iter != gThemes.end(); ++iter )
+  for(NamedThemes::iterator iter = gThemes.begin(); iter != gThemes.end(); ++iter)
   {
     NamedTheme& theme = *iter;
-    if( theme.name == name )
+    if(theme.name == name)
     {
       theme.theme = output;
       return;
     }
   }
 
-  gThemes.push_back( NamedTheme( name, output ) );
+  gThemes.push_back(NamedTheme(name, output));
 }
 
 void SetDefaultFontFamily(const std::string& family)
@@ -289,10 +308,10 @@ void SetDefaultFontStyle(const std::string& style)
   gFontStyle = style;
 }
 
-void SetDefaultFontSize( float size )
+void SetDefaultFontSize(float size)
 {
   gFontSize = size;
 }
 
-} // StyleMonitor
-} // Test
+} // namespace StyleMonitor
+} // namespace Test
index f63b5cf..63222a0 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <toolkit-environment-variable.h>
 #include <toolkit-event-thread-callback.h>
+#include <toolkit-style-monitor.h>
 #include <toolkit-texture-upload-manager.h>
 #include <toolkit-timer.h>
 
@@ -74,6 +75,22 @@ const char* TEST_N_PATCH_IMAGE_FILE_NAME  = TEST_RESOURCE_DIR "/heartsframe.9.pn
 constexpr auto LOAD_IMAGE_YUV_PLANES_ENV         = "DALI_LOAD_IMAGE_YUV_PLANES";
 constexpr auto ENABLE_DECODE_JPEG_TO_YUV_420_ENV = "DALI_ENABLE_DECODE_JPEG_TO_YUV_420";
 
+constexpr auto DALI_DEBUG_IMAGE_VISUAL_SHADER_ENV = "DALI_DEBUG_IMAGE_VISUAL_SHADER";
+
+constexpr auto DALI_DEBUG_IMAGE_VISUAL_SHADER_SCRIPT_FILE_NAME_ENV = "DALI_DEBUG_IMAGE_VISUAL_SHADER_SCRIPT_FILE_NAME";
+
+const char* VALID_DEBUG_SHADER_SCRIPT =
+  "{\n"
+  "  \"maximumColorRate\": 0.5,\n"
+  "  \"redChannelCodes\":\n"
+  "  {\n"
+  "    \"triggerCode\":[\"return\",\" false;\"],\n"
+  "    \"ratioCode\":\"return 0.0;\"\n"
+  "  }\n"
+  "}\n";
+
+constexpr std::string_view THROW_EXCEPTION_STYLE_FILE_NAME = "throwException";
+
 bool             gResourceReadySignalFired = false;
 std::vector<int> gReadyIds                 = {};
 void             ResourceReadySignal(Control control)
@@ -3984,4 +4001,139 @@ int UtcDaliImageVisualLoadFastTrackImagePlanes02(void)
   application.Render();
 
   END_TEST;
+}
+
+int UtcDaliImageVisualDebugImageVisualShaderP1(void)
+{
+  EnvironmentVariable::SetTestEnvironmentVariable(DALI_DEBUG_IMAGE_VISUAL_SHADER_ENV, "1");
+  EnvironmentVariable::SetTestEnvironmentVariable(DALI_DEBUG_IMAGE_VISUAL_SHADER_SCRIPT_FILE_NAME_ENV, "validFile"); // Try to load not exist file.
+
+  // Set valid script file
+  Test::StyleMonitor::SetThemeFileOutput("validFile", VALID_DEBUG_SHADER_SCRIPT);
+
+  ToolkitTestApplication application;
+
+  VisualFactory factory = VisualFactory::Get();
+  DALI_TEST_CHECK(factory);
+
+  Property::Map propertyMap;
+  propertyMap.Insert(Toolkit::Visual::Property::TYPE, Visual::IMAGE);
+  propertyMap.Insert(ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME);
+
+  Visual::Base visual = factory.CreateVisual(propertyMap);
+  DALI_TEST_CHECK(visual);
+
+  DummyControl      actor     = DummyControl::New();
+  DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+  dummyImpl.RegisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1, visual);
+  actor.SetProperty(Actor::Property::SIZE, Vector2(200.f, 200.f));
+  application.GetScene().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+  TestGlAbstraction& gl           = application.GetGlAbstraction();
+  TraceCallStack&    textureTrace = gl.GetTextureTrace();
+  textureTrace.Enable(true);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
+  DALI_TEST_EQUALS(actor.IsResourceReady(), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(textureTrace.CountMethod("GenTextures"), 1, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliImageVisualDebugImageVisualShaderN1(void)
+{
+  EnvironmentVariable::SetTestEnvironmentVariable(DALI_DEBUG_IMAGE_VISUAL_SHADER_ENV, "1");
+  EnvironmentVariable::SetTestEnvironmentVariable(DALI_DEBUG_IMAGE_VISUAL_SHADER_SCRIPT_FILE_NAME_ENV, "notJsonFile"); // Try to load exist file, but not a json
+
+  // Set invalid script file
+  Test::StyleMonitor::SetThemeFileOutput("notJsonFile", "1");
+
+  ToolkitTestApplication application;
+
+  VisualFactory factory = VisualFactory::Get();
+  DALI_TEST_CHECK(factory);
+
+  Property::Map propertyMap;
+  propertyMap.Insert(Toolkit::Visual::Property::TYPE, Visual::IMAGE);
+  propertyMap.Insert(ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME);
+
+  Visual::Base visual = factory.CreateVisual(propertyMap);
+  DALI_TEST_CHECK(visual);
+
+  DummyControl      actor     = DummyControl::New();
+  DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+  dummyImpl.RegisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1, visual);
+  actor.SetProperty(Actor::Property::SIZE, Vector2(200.f, 200.f));
+  application.GetScene().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+  TestGlAbstraction& gl           = application.GetGlAbstraction();
+  TraceCallStack&    textureTrace = gl.GetTextureTrace();
+  textureTrace.Enable(true);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
+  DALI_TEST_EQUALS(actor.IsResourceReady(), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(textureTrace.CountMethod("GenTextures"), 1, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliImageVisualDebugImageVisualShaderN2(void)
+{
+  EnvironmentVariable::SetTestEnvironmentVariable(DALI_DEBUG_IMAGE_VISUAL_SHADER_ENV, "1");
+  EnvironmentVariable::SetTestEnvironmentVariable(DALI_DEBUG_IMAGE_VISUAL_SHADER_SCRIPT_FILE_NAME_ENV, std::string(THROW_EXCEPTION_STYLE_FILE_NAME).c_str()); // Try to load file that throw some exception
+
+  // Set throw exception script file
+  Test::StyleMonitor::SetThemeFileOutput(std::string(THROW_EXCEPTION_STYLE_FILE_NAME), "1");
+
+  ToolkitTestApplication application;
+
+  VisualFactory factory = VisualFactory::Get();
+  DALI_TEST_CHECK(factory);
+
+  Property::Map propertyMap;
+  propertyMap.Insert(Toolkit::Visual::Property::TYPE, Visual::IMAGE);
+  propertyMap.Insert(ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME);
+
+  Visual::Base visual = factory.CreateVisual(propertyMap);
+  DALI_TEST_CHECK(visual);
+
+  DummyControl      actor     = DummyControl::New();
+  DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+  dummyImpl.RegisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1, visual);
+  actor.SetProperty(Actor::Property::SIZE, Vector2(200.f, 200.f));
+  application.GetScene().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+  TestGlAbstraction& gl           = application.GetGlAbstraction();
+  TraceCallStack&    textureTrace = gl.GetTextureTrace();
+  textureTrace.Enable(true);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
+  DALI_TEST_EQUALS(actor.IsResourceReady(), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(textureTrace.CountMethod("GenTextures"), 1, TEST_LOCATION);
+
+  END_TEST;
 }
\ No newline at end of file
index 3b5d390..f7b7db1 100644 (file)
@@ -197,7 +197,7 @@ void PhysicsDebugRenderer::RenderLines(const Dali::RenderCallbackInput& input)
   // But, it appears to be bugged.
 
   glBindBuffer(GL_ARRAY_BUFFER, mBufferId);
-  glBufferData(GL_ARRAY_BUFFER, mLines.size() * sizeof(VertexLine), &mLines[0], GL_STATIC_DRAW);
+  glBufferData(GL_ARRAY_BUFFER, GLsizeiptr(mLines.size() * sizeof(VertexLine)), &mLines[0], GL_STATIC_DRAW);
 
   glVertexAttribPointer(mVertexLocation, 3, GL_FLOAT, GL_FALSE, 24, 0);
   glEnableVertexAttribArray(mVertexLocation);
index 8331e14..9c776c6 100644 (file)
@@ -267,9 +267,9 @@ void PhysicsDebugRenderer::RenderLines(const Dali::RenderCallbackInput& input)
   glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 
   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBufferId);
-  glBufferData(GL_ELEMENT_ARRAY_BUFFER, mIndices.size() * sizeof(uint16_t), &mIndices[0], GL_STATIC_DRAW);
+  glBufferData(GL_ELEMENT_ARRAY_BUFFER, GLsizeiptr(mIndices.size() * sizeof(uint16_t)), &mIndices[0], GL_STATIC_DRAW);
   glBindBuffer(GL_ARRAY_BUFFER, mVertexBufferId);
-  glBufferData(GL_ARRAY_BUFFER, mVertices.size() * sizeof(Vertex), &mVertices[0], GL_STATIC_DRAW);
+  glBufferData(GL_ARRAY_BUFFER, GLsizeiptr(mVertices.size() * sizeof(Vertex)), &mVertices[0], GL_STATIC_DRAW);
 
   GLint stride = 52; // 4*(2 + 2 + 1 + 4 + 4) = 4*13=52
   glVertexAttribPointer(mPositionLocation, 2, GL_FLOAT, GL_FALSE, stride, 0);
index 7274e9c..e9ae5b7 100644 (file)
@@ -53,6 +53,7 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/visuals/text-visual-shader-factory.cpp
    ${toolkit_src_dir}/visuals/text/text-visual.cpp
    ${toolkit_src_dir}/visuals/transition-data-impl.cpp
+   ${toolkit_src_dir}/visuals/image-visual-shader-debug.cpp
    ${toolkit_src_dir}/visuals/image-visual-shader-factory.cpp
    ${toolkit_src_dir}/visuals/image-visual-shader-feature-builder.cpp
    ${toolkit_src_dir}/visuals/visual-base-data-impl.cpp
index 3ee2331..1c9f619 100644 (file)
@@ -680,6 +680,7 @@ void KeyboardFocusManager::ClearFocus()
   Actor actor = GetCurrentFocusActor();
   if(actor)
   {
+    DALI_LOG_RELEASE_INFO("ClearFocus id:(%d)\n",  actor.GetProperty<int32_t>(Dali::Actor::Property::ID));
     // Send notification for the change of focus actor
     if(!mFocusChangedSignal.Empty())
     {
index 88da9b7..9e1986c 100644 (file)
@@ -106,8 +106,9 @@ void KeyInputFocusManager::SetFocus(Toolkit::Control control)
 
 void KeyInputFocusManager::RemoveFocus(Toolkit::Control control)
 {
-  if(control == mCurrentFocusControl)
+  if(control && control == mCurrentFocusControl)
   {
+    DALI_LOG_RELEASE_INFO("RemoveFocus id:(%d)\n", control.GetProperty<int32_t>(Dali::Actor::Property::ID));
     control.OffSceneSignal().Disconnect(mSlotDelegate, &KeyInputFocusManager::OnFocusControlSceneDisconnection);
 
     mCurrentFocusControl.Reset();
index f13f865..12ba3c4 100644 (file)
@@ -1,5 +1,5 @@
 INPUT mediump vec2 vTexCoord;
-#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
+#if defined(IS_REQUIRED_DEBUG_VISUAL_SHADER) || defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
 INPUT mediump vec2 vPosition;
 INPUT mediump vec2 vRectSize;
 INPUT mediump vec2 vOptRectSize;
@@ -28,6 +28,11 @@ uniform mediump vec4 uAtlasRect;
 uniform lowp vec2 wrapMode;
 #endif
 
+
+#if defined(IS_REQUIRED_DEBUG_VISUAL_SHADER)
+uniform highp vec3 uScale;
+#endif
+
 uniform lowp vec4 uColor;
 uniform lowp vec3 mixColor;
 uniform lowp float preMultipliedAlpha;
@@ -50,7 +55,7 @@ mediump float wrapCoordinate( mediump vec2 range, mediump float coordinate, lowp
 }
 #endif
 
-#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
+#if defined(IS_REQUIRED_DEBUG_VISUAL_SHADER) || defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
 // Global values both rounded corner and borderline use
 
 // radius of rounded corner on this quadrant
@@ -238,6 +243,122 @@ lowp vec4 ConvertYuvToRgba(mediump vec2 texCoord)
 }
 #endif
 
+#ifdef IS_REQUIRED_DEBUG_VISUAL_SHADER
+
+// Predefined values whether some macro defined or not.
+// Since we make debug codes replace by macro,
+// sharp if keyword cannot be used.
+// Instead, let we use bool values so we can use define checked in script
+#ifdef IS_REQUIRED_ROUNDED_CORNER
+const bool IS_REQUIRED_ROUNDED_CORNER_BOOL = true;
+#else
+const bool IS_REQUIRED_ROUNDED_CORNER_BOOL = false;
+#endif
+#ifdef IS_REQUIRED_BORDERLINE
+const bool IS_REQUIRED_BORDERLINE_BOOL = true;
+#else
+const bool IS_REQUIRED_BORDERLINE_BOOL = false;
+#endif
+#ifdef IS_REQUIRED_YUV_TO_RGB
+const bool IS_REQUIRED_YUV_TO_RGB_BOOL = true;
+#else
+const bool IS_REQUIRED_YUV_TO_RGB_BOOL = false;
+#endif
+#ifdef IS_REQUIRED_UNIFIED_YUV_AND_RGB
+const bool IS_REQUIRED_UNIFIED_YUV_AND_RGB_BOOL = true;
+#else
+const bool IS_REQUIRED_UNIFIED_YUV_AND_RGB_BOOL = false;
+#endif
+#ifdef IS_REQUIRED_ALPHA_MASKING
+const bool IS_REQUIRED_ALPHA_MASKING_BOOL = true;
+#else
+const bool IS_REQUIRED_ALPHA_MASKING_BOOL = false;
+#endif
+#ifdef ATLAS_DEFAULT_WARP
+const bool ATLAS_DEFAULT_WARP_BOOL = true;
+#else
+const bool ATLAS_DEFAULT_WARP_BOOL = false;
+#endif
+#ifdef ATLAS_CUSTOM_WARP
+const bool ATLAS_CUSTOM_WARP_BOOL = true;
+#else
+const bool ATLAS_CUSTOM_WARP_BOOL = false;
+#endif
+
+// These lines in the shader may be replaced with actual definitions by the debug-image-visual-shader-script.json.
+// DEBUG_TRIGGER_CODE return bool type, and DEBUG_RATIO_CODE return float value which will be clamped between 0.0 and 1.0
+// If DEBUG_TRIGGER_CODE return true, it mean we will change final color's channel value.
+// If ratio is 0.0, debug color rate become MINIMUM_DEBUG_COLOR_RATE, and 1.0 than MAXIMUM_DEBUG_COLOR_RATE.
+#define MINIMUM_DEBUG_COLOR_RATE
+#define MAXIMUM_DEBUG_COLOR_RATE
+#define DEBUG_TRIGGER_RED_CODE
+#define DEBUG_TRIGGER_GREEN_CODE
+#define DEBUG_TRIGGER_BLUE_CODE
+#define DEBUG_RATIO_RED_CODE
+#define DEBUG_RATIO_GREEN_CODE
+#define DEBUG_RATIO_BLUE_CODE
+
+const mediump float gMinDebugColorRate = MINIMUM_DEBUG_COLOR_RATE;
+const mediump float gMaxDebugColorRate = MAXIMUM_DEBUG_COLOR_RATE;
+
+bool DebugTriggerRed(mediump vec4 originColor)
+{
+  DEBUG_TRIGGER_RED_CODE
+}
+
+bool DebugTriggerGreen(mediump vec4 originColor)
+{
+  DEBUG_TRIGGER_GREEN_CODE
+}
+
+bool DebugTriggerBlue(mediump vec4 originColor)
+{
+  DEBUG_TRIGGER_BLUE_CODE
+}
+
+mediump float DebugRatioRed(mediump vec4 originColor)
+{
+  DEBUG_RATIO_RED_CODE
+}
+
+mediump float DebugRatioGreen(mediump vec4 originColor)
+{
+  DEBUG_RATIO_GREEN_CODE
+}
+
+mediump float DebugRatioBlue(mediump vec4 originColor)
+{
+  DEBUG_RATIO_BLUE_CODE
+}
+
+mediump vec3 ApplyDebugMixColor(mediump vec4 originColor)
+{
+  mediump float debugColorRateRed = 0.0;
+  mediump float debugColorRateGreen = 0.0;
+  mediump float debugColorRateBlue = 0.0;
+
+  if(DebugTriggerRed(originColor))
+  {
+    debugColorRateRed = mix(gMinDebugColorRate, gMaxDebugColorRate, smoothstep(0.0, 1.0, DebugRatioRed(originColor)));
+  }
+  if(DebugTriggerGreen(originColor))
+  {
+    debugColorRateGreen = mix(gMinDebugColorRate, gMaxDebugColorRate, smoothstep(0.0, 1.0, DebugRatioGreen(originColor)));
+  }
+  if(DebugTriggerBlue(originColor))
+  {
+    debugColorRateBlue = mix(gMinDebugColorRate, gMaxDebugColorRate, smoothstep(0.0, 1.0, DebugRatioBlue(originColor)));
+  }
+
+  mediump float colorRate = max(debugColorRateRed, max(debugColorRateGreen, debugColorRateBlue));
+  mediump vec3 debugColor = vec3(debugColorRateRed, debugColorRateGreen, debugColorRateBlue);
+
+  debugColor *= mix(1.0, originColor.a, preMultipliedAlpha);
+
+  return originColor.rgb * (1.0 - colorRate) + debugColor;
+}
+#endif
+
 void main()
 {
 #ifdef ATLAS_DEFAULT_WARP
@@ -263,13 +384,15 @@ void main()
   textureColor.rgb *= mix(1.0, maskAlpha, preMultipliedAlpha);
 #endif
 
-#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
+#if defined(IS_REQUIRED_DEBUG_VISUAL_SHADER) || defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
+#ifndef IS_REQUIRED_DEBUG_VISUAL_SHADER
   // skip most potential calculate for performance
   if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y)
   {
     OUT_COLOR = textureColor;
   }
   else
+#endif
   {
     PreprocessPotential();
 #endif
@@ -285,7 +408,11 @@ void main()
     OUT_COLOR.rgb *= mix(1.0, opacity, preMultipliedAlpha);
 #endif
 
-#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
+#if defined(IS_REQUIRED_DEBUG_VISUAL_SHADER) || defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
   }
 #endif
+
+#ifdef IS_REQUIRED_DEBUG_VISUAL_SHADER
+  OUT_COLOR.rgb = ApplyDebugMixColor(OUT_COLOR);
+#endif
 }
index 6109c29..d5b4fcf 100644 (file)
@@ -1,6 +1,6 @@
 INPUT mediump vec2 aPosition;
 OUTPUT mediump vec2 vTexCoord;
-#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
+#if defined(IS_REQUIRED_DEBUG_VISUAL_SHADER) || defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
 OUTPUT mediump vec2 vPosition;
 OUTPUT mediump vec2 vRectSize;
 OUTPUT mediump vec2 vOptRectSize;
@@ -14,7 +14,7 @@ uniform highp mat4 uMvpMatrix;
 uniform highp vec3 uSize;
 uniform mediump vec4 pixelArea;
 
-#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
+#if defined(IS_REQUIRED_DEBUG_VISUAL_SHADER) || defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
 // Be used when we calculate anti-alias range near 1 pixel.
 uniform highp vec3 uScale;
 #endif
@@ -45,7 +45,7 @@ vec4 ComputeVertexPosition()
   vec2 visualSize = mix(size * uSize.xy, size, offsetSizeMode.zw) + extraSize;
   vec2 visualOffset = mix(offset * uSize.xy, offset, offsetSizeMode.xy);
 
-#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
+#if defined(IS_REQUIRED_DEBUG_VISUAL_SHADER) || defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
   vRectSize = visualSize * 0.5;
   vOptRectSize = vRectSize;
 
@@ -86,7 +86,7 @@ vec4 ComputeVertexPosition()
 #ifdef IS_REQUIRED_BORDERLINE
   vPosition = aPosition * (visualSize + outerBorderlineSize + vertexMargin);
   vOptRectSize -= (borderlineWidth - outerBorderlineSize * 0.5) + 1.0;
-#elif defined(IS_REQUIRED_ROUNDED_CORNER)
+#elif defined(IS_REQUIRED_DEBUG_VISUAL_SHADER) || defined(IS_REQUIRED_ROUNDED_CORNER)
   vPosition = aPosition * (visualSize + vertexMargin);
 #else
   mediump vec2 vPosition = aPosition * visualSize;
index 4bb2471..0c3b3bb 100644 (file)
@@ -118,12 +118,12 @@ void VectorAnimationTask::Finalize()
   // Release some objects in the main thread
   if(mAnimationFinishedCallback)
   {
-    mVectorAnimationThread.RemoveEventTriggerCallback(mAnimationFinishedCallback.get());
+    mVectorAnimationThread.RemoveEventTriggerCallbacks(mAnimationFinishedCallback.get());
     mAnimationFinishedCallback.reset();
   }
   if(mLoadCompletedCallback)
   {
-    mVectorAnimationThread.RemoveEventTriggerCallback(mLoadCompletedCallback.get());
+    mVectorAnimationThread.RemoveEventTriggerCallbacks(mLoadCompletedCallback.get());
     mLoadCompletedCallback.reset();
   }
 
index 66a9f14..8f70ae3 100644 (file)
@@ -163,14 +163,11 @@ void VectorAnimationThread::AddEventTriggerCallback(CallbackBase* callback)
   }
 }
 
-void VectorAnimationThread::RemoveEventTriggerCallback(CallbackBase* callback)
+void VectorAnimationThread::RemoveEventTriggerCallbacks(CallbackBase* callback)
 {
   ConditionalWait::ScopedLock lock(mConditionalWait);
-  auto                        iter = std::find(mTriggerEventCallbacks.begin(), mTriggerEventCallbacks.end(), callback);
-  if(iter != mTriggerEventCallbacks.end())
-  {
-    mTriggerEventCallbacks.erase(iter);
-  }
+  auto                        iter = std::remove(mTriggerEventCallbacks.begin(), mTriggerEventCallbacks.end(), callback);
+  mTriggerEventCallbacks.erase(iter, mTriggerEventCallbacks.end());
 }
 
 void VectorAnimationThread::Run()
index 07537c5..a5108d5 100644 (file)
@@ -82,11 +82,11 @@ public:
   void AddEventTriggerCallback(CallbackBase* callback);
 
   /**
-   * @brief Remove an event trigger callback.
+   * @brief Remove event trigger callbacks what we added before.
    *
    * @param callback The callback to remove
    */
-  void RemoveEventTriggerCallback(CallbackBase* callback);
+  void RemoveEventTriggerCallbacks(CallbackBase* callback);
 
 protected:
   /**
diff --git a/dali-toolkit/internal/visuals/image-visual-shader-debug.cpp b/dali-toolkit/internal/visuals/image-visual-shader-debug.cpp
new file mode 100644 (file)
index 0000000..9a5cca6
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/visuals/image-visual-shader-debug.h>
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/environment-variable.h>
+#include <dali/devel-api/adaptor-framework/style-monitor.h> ///< for load json file.
+
+#include <regex> ///< for redefine shader
+#include <string_view>
+
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
+#include <dali-toolkit/devel-api/builder/json-parser.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+namespace
+{
+constexpr auto DALI_DEBUG_IMAGE_VISUAL_SHADER_ENV = "DALI_DEBUG_IMAGE_VISUAL_SHADER";
+
+bool DebugImageVisualShaderEnvironmentEnabled()
+{
+  static bool enabled       = false;
+  static bool enabledSetted = false;
+  if(!enabledSetted)
+  {
+    enabledSetted           = true;
+    auto debugEnabledString = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_DEBUG_IMAGE_VISUAL_SHADER_ENV);
+    enabled                 = debugEnabledString ? std::atoi(debugEnabledString) : false;
+  }
+  return enabled;
+}
+
+constexpr auto DALI_DEBUG_IMAGE_VISUAL_SHADER_SCRIPT_FILE_NAME_ENV = "DALI_DEBUG_IMAGE_VISUAL_SHADER_SCRIPT_FILE_NAME";
+constexpr auto DEFAULT_DEBUG_IMAGE_VISUAL_SHADER_SCRIPT_FILE_NAME  = "debug-image-visual-shader-script.json";
+
+const std::string& GetScriptFilename()
+{
+  // Set the full path for the default script file.
+  const static std::string styleDirPath{AssetManager::GetDaliStylePath()};
+  static std::string       mScriptFileName{};
+
+  if(DALI_UNLIKELY(mScriptFileName.empty()))
+  {
+    // Use user's own script if exist.
+    auto environmentScriptFilename = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_DEBUG_IMAGE_VISUAL_SHADER_SCRIPT_FILE_NAME_ENV);
+
+    mScriptFileName = environmentScriptFilename ? std::string(environmentScriptFilename) : styleDirPath + std::string(DEFAULT_DEBUG_IMAGE_VISUAL_SHADER_SCRIPT_FILE_NAME);
+
+    DALI_ASSERT_DEBUG(0 != mScriptFileName.length());
+  }
+
+  return mScriptFileName;
+}
+
+bool LoadJsonScript(std::string& stringOut)
+{
+  auto styleMonitor = StyleMonitor::Get();
+
+  // as toolkit is platform agnostic, it cannot load files from filesystem
+  // ask style monitor to load the style sheet
+  if(styleMonitor)
+  {
+    try
+    {
+      return styleMonitor.LoadThemeFile(GetScriptFilename(), stringOut);
+    }
+    catch(const std::exception& e)
+    {
+      DALI_LOG_ERROR("Something system exception throwed during load script file![%s]\n", GetScriptFilename().c_str());
+      DALI_LOG_ERROR("Error message : [%s]\n", e.what());
+    }
+    catch(const Dali::DaliException& e)
+    {
+      DALI_LOG_ERROR("Something Dali exception throwed during load script file![%s]\n", GetScriptFilename().c_str());
+      DALI_LOG_ERROR("Error message : [%s]\n", e.condition);
+    }
+    catch(...)
+    {
+      DALI_LOG_ERROR("Something unkown exception throwed during load script file![%s]\n", GetScriptFilename().c_str());
+    }
+  }
+
+  return false;
+}
+// Json keywords what we will get information from json.
+constexpr std::string_view MINIMUM_DEBUG_COLOR_RATE_JSON_KEY = "minimumColorRate";
+constexpr std::string_view MAXIMUM_DEBUG_COLOR_RATE_JSON_KEY = "maximumColorRate";
+constexpr std::string_view DEBUG_RED_CHANNEL_CODE_JSON_KEY   = "redChannelCodes";
+constexpr std::string_view DEBUG_GREEN_CHANNEL_CODE_JSON_KEY = "greenChannelCodes";
+constexpr std::string_view DEBUG_BLUE_CHANNEL_CODE_JSON_KEY  = "blueChannelCodes";
+constexpr std::string_view DEBUG_TRIGGER_CODE_JSON_KEY       = "triggerCode";
+constexpr std::string_view DEBUG_RATIO_CODE_JSON_KEY         = "ratioCode";
+
+// Macro keywords what we will replace at fragment shader.
+constexpr std::string_view MINIMUM_DEBUG_COLOR_RATE_MACRO_KEY = "MINIMUM_DEBUG_COLOR_RATE";
+constexpr std::string_view MAXIMUM_DEBUG_COLOR_RATE_MACRO_KEY = "MAXIMUM_DEBUG_COLOR_RATE";
+constexpr std::string_view DEBUG_TRIGGER_RED_CODE_MACRO_KEY   = "DEBUG_TRIGGER_RED_CODE";
+constexpr std::string_view DEBUG_TRIGGER_GREEN_CODE_MACRO_KEY = "DEBUG_TRIGGER_GREEN_CODE";
+constexpr std::string_view DEBUG_TRIGGER_BLUE_CODE_MACRO_KEY  = "DEBUG_TRIGGER_BLUE_CODE";
+constexpr std::string_view DEBUG_RATIO_RED_CODE_MACRO_KEY     = "DEBUG_RATIO_RED_CODE";
+constexpr std::string_view DEBUG_RATIO_GREEN_CODE_MACRO_KEY   = "DEBUG_RATIO_GREEN_CODE";
+constexpr std::string_view DEBUG_RATIO_BLUE_CODE_MACRO_KEY    = "DEBUG_RATIO_BLUE_CODE";
+
+// Default macro keywords when we fail to parse script.
+constexpr std::string_view DEFAULT_DEBUG_COLOR_RATE_MACRO_VALUE   = "0.0";
+constexpr std::string_view DEFAULT_DEBUG_TRIGGER_CODE_MACRO_VALUE = "return false;";
+constexpr std::string_view DEFAULT_DEBUG_RATIO_CODE_MACRO_VALUE   = "return 0.0;";
+
+bool ParseScriptInfomation(Property::Map& result)
+{
+  std::string stringOut;
+  if(!LoadJsonScript(stringOut))
+  {
+    DALI_LOG_ERROR("Fail to load script file [%s]\n", GetScriptFilename().c_str());
+    return false;
+  }
+
+  Toolkit::JsonParser parser = Toolkit::JsonParser::New();
+
+  if(!parser.Parse(stringOut))
+  {
+    std::ostringstream stream;
+    if(parser.ParseError())
+    {
+      stream << "position: " << parser.GetErrorPosition() << ", line: " << parser.GetErrorLineNumber() << ", column: " << parser.GetErrorColumn() << ", description: " << parser.GetErrorDescription() << ".";
+    }
+    DALI_LOG_ERROR("Fail to parse json script\nError : %s\nJson : %s\n", stream.str().c_str(), stringOut.c_str());
+    return false;
+  }
+
+  const auto* rootNode = parser.GetRoot();
+  if(!rootNode)
+  {
+    DALI_LOG_ERROR("Fail to get root node\n");
+    return false;
+  }
+
+  auto InsertScriptMap = [](Property::Map& result, const TreeNode* node, const std::string_view& jsonKey, const std::string_view& macroKey, const std::string_view& defaultValue) {
+    std::ostringstream oss;
+    oss.clear();
+
+    if(node)
+    {
+      const auto* childNode = node->GetChild(jsonKey);
+
+      if(childNode)
+      {
+        if(childNode->GetType() == TreeNode::FLOAT)
+        {
+          oss << childNode->GetFloat();
+        }
+        else if(childNode->GetType() == TreeNode::STRING)
+        {
+          oss << childNode->GetString();
+        }
+        else if(childNode->GetType() == TreeNode::ARRAY)
+        {
+          // Concat strings with line feed
+          bool isFirst = true;
+          for(auto iter = childNode->CBegin(), endIter = childNode->CEnd(); iter != endIter; ++iter)
+          {
+            if((*iter).second.GetType() == TreeNode::STRING)
+            {
+              if(isFirst)
+              {
+                isFirst = false;
+              }
+              else
+              {
+                oss << "\n";
+              }
+              oss << (*iter).second.GetString();
+            }
+          }
+        }
+      }
+    }
+
+    if(oss.str().empty())
+    {
+      oss << defaultValue;
+    }
+    result.Insert(std::string(macroKey), oss.str());
+  };
+
+  auto InsertChannelScriptMap = [&InsertScriptMap](Property::Map& result, const TreeNode* node, const std::string_view& channelJsonKey, const std::string_view& triggerMacroKey, const std::string_view& ratioMacroKey) {
+    const auto* channelNode = node->GetChild(channelJsonKey);
+    InsertScriptMap(result, channelNode, DEBUG_TRIGGER_CODE_JSON_KEY, triggerMacroKey, DEFAULT_DEBUG_TRIGGER_CODE_MACRO_VALUE);
+    InsertScriptMap(result, channelNode, DEBUG_RATIO_CODE_JSON_KEY, ratioMacroKey, DEFAULT_DEBUG_RATIO_CODE_MACRO_VALUE);
+  };
+
+  // Get color rate
+  InsertScriptMap(result, rootNode, MINIMUM_DEBUG_COLOR_RATE_JSON_KEY, MINIMUM_DEBUG_COLOR_RATE_MACRO_KEY, DEFAULT_DEBUG_COLOR_RATE_MACRO_VALUE);
+  InsertScriptMap(result, rootNode, MAXIMUM_DEBUG_COLOR_RATE_JSON_KEY, MAXIMUM_DEBUG_COLOR_RATE_MACRO_KEY, DEFAULT_DEBUG_COLOR_RATE_MACRO_VALUE);
+
+  // Get each color ChannelCodes
+  InsertChannelScriptMap(result, rootNode, DEBUG_RED_CHANNEL_CODE_JSON_KEY, DEBUG_TRIGGER_RED_CODE_MACRO_KEY, DEBUG_RATIO_RED_CODE_MACRO_KEY);
+  InsertChannelScriptMap(result, rootNode, DEBUG_GREEN_CHANNEL_CODE_JSON_KEY, DEBUG_TRIGGER_GREEN_CODE_MACRO_KEY, DEBUG_RATIO_GREEN_CODE_MACRO_KEY);
+  InsertChannelScriptMap(result, rootNode, DEBUG_BLUE_CHANNEL_CODE_JSON_KEY, DEBUG_TRIGGER_BLUE_CODE_MACRO_KEY, DEBUG_RATIO_BLUE_CODE_MACRO_KEY);
+
+  return true;
+}
+
+const Property::Map& GetScriptInfomation()
+{
+  static Property::Map result;
+
+  if(DALI_UNLIKELY(result.Empty()))
+  {
+    if(!ParseScriptInfomation(result))
+    {
+      // Use default script information if parse failed.
+      result.Clear();
+
+      result.Insert(std::string(MINIMUM_DEBUG_COLOR_RATE_MACRO_KEY), std::string(DEFAULT_DEBUG_COLOR_RATE_MACRO_VALUE));
+      result.Insert(std::string(MAXIMUM_DEBUG_COLOR_RATE_MACRO_KEY), std::string(DEFAULT_DEBUG_COLOR_RATE_MACRO_VALUE));
+      result.Insert(std::string(DEBUG_TRIGGER_RED_CODE_MACRO_KEY), std::string(DEFAULT_DEBUG_TRIGGER_CODE_MACRO_VALUE));
+      result.Insert(std::string(DEBUG_TRIGGER_GREEN_CODE_MACRO_KEY), std::string(DEFAULT_DEBUG_TRIGGER_CODE_MACRO_VALUE));
+      result.Insert(std::string(DEBUG_TRIGGER_BLUE_CODE_MACRO_KEY), std::string(DEFAULT_DEBUG_TRIGGER_CODE_MACRO_VALUE));
+      result.Insert(std::string(DEBUG_RATIO_RED_CODE_MACRO_KEY), std::string(DEFAULT_DEBUG_RATIO_CODE_MACRO_VALUE));
+      result.Insert(std::string(DEBUG_RATIO_GREEN_CODE_MACRO_KEY), std::string(DEFAULT_DEBUG_RATIO_CODE_MACRO_VALUE));
+      result.Insert(std::string(DEBUG_RATIO_BLUE_CODE_MACRO_KEY), std::string(DEFAULT_DEBUG_RATIO_CODE_MACRO_VALUE));
+    }
+  }
+
+  return result;
+}
+
+void RedefineMacro(std::string& shaderCode, std::string macro, std::string value)
+{
+  std::string definition = "#define " + macro;
+  std::size_t found      = shaderCode.find(definition);
+  DALI_ASSERT_ALWAYS(found != std::string::npos && "Macro keyword was not exist in shader code!");
+
+  std::size_t insertionPoint = found + definition.length();
+
+  // Automatically insert line-continuation character into value
+  std::regex                 re("\n");
+  std::sregex_token_iterator first{value.begin(), value.end(), re, -1}, last;
+  for(auto i = first; i != last; ++i)
+  {
+    std::string line = std::string(" \\\n") + (*i).str();
+    shaderCode.insert(insertionPoint, line);
+    insertionPoint += line.length();
+  }
+}
+
+} // namespace
+
+namespace ImageVisualShaderDebug
+{
+bool DebugImageVisualShaderEnabled()
+{
+  return DebugImageVisualShaderEnvironmentEnabled();
+}
+
+void ApplyImageVisualShaderDebugScriptCode(std::string& fragmentShader)
+{
+  const auto& resultMap = GetScriptInfomation();
+
+  for(std::size_t i = 0u; i < resultMap.Count(); ++i)
+  {
+    auto key   = resultMap.GetKeyAt(i);
+    auto value = resultMap.GetValue(i);
+
+    RedefineMacro(fragmentShader, std::move(key.stringKey), value.Get<std::string>());
+  }
+}
+} // namespace ImageVisualShaderDebug
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/image-visual-shader-debug.h b/dali-toolkit/internal/visuals/image-visual-shader-debug.h
new file mode 100644 (file)
index 0000000..972ff56
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef DALI_TOOLKIT_IMAGE_VISUAL_SHADER_DEBUG_H
+#define DALI_TOOLKIT_IMAGE_VISUAL_SHADER_DEBUG_H
+
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+namespace ImageVisualShaderDebug
+{
+/**
+ * @brief Check whether we need to use debug option for image visual.
+ *
+ * @return True if ImageVisualShader relative environment on. False otherwise.
+ */
+bool DebugImageVisualShaderEnabled();
+
+/**
+ * @brief Apply fragment shader use debug script.
+ *
+ * @param[in, out] fragmentShader Shader code to apply debug script.
+ */
+void ApplyImageVisualShaderDebugScriptCode(std::string& fragmentShader);
+
+} // namespace ImageVisualShaderDebug
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_IMAGE_VISUAL_SHADER_DEBUG_H
index 7bbe186..1f3092f 100644 (file)
@@ -22,6 +22,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
+#include <dali-toolkit/internal/visuals/image-visual-shader-debug.h>
 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
 #include <dali/integration-api/debug.h>
 
@@ -35,31 +36,29 @@ namespace
 {
 const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
 
-const int                         NATIVE_SHADER_TYPE_OFFSET = VisualFactoryCache::ShaderType::NATIVE_IMAGE_SHADER - VisualFactoryCache::ShaderType::IMAGE_SHADER;
-static constexpr std::string_view Y_FLIP_MASK_TEXTURE       = "uYFlipMaskTexture";
-static constexpr float            NOT_FLIP_MASK_TEXTURE     = 0.0f;
-} // unnamed namespace
+constexpr int              NATIVE_SHADER_TYPE_OFFSET = VisualFactoryCache::ShaderType::NATIVE_IMAGE_SHADER - VisualFactoryCache::ShaderType::IMAGE_SHADER;
+constexpr std::string_view Y_FLIP_MASK_TEXTURE       = "uYFlipMaskTexture";
+constexpr float            NOT_FLIP_MASK_TEXTURE     = 0.0f;
 
-static constexpr auto          SHADER_TYPE_COUNT = 6u;
+constexpr auto SHADER_TYPE_COUNT = 6u;
 
-const std::string_view VertexPredefines[SHADER_TYPE_COUNT]
-{
-  "", // VisualFactoryCache::IMAGE_SHADER,
-  "#define IS_REQUIRED_ROUNDED_CORNER\n", //VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER,
-  "",//VisualFactoryCache::IMAGE_SHADER_YUV_TO_RGB,
-  "#define IS_REQUIRED_ROUNDED_CORNER\n",//VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_TO_RGB,
-  "",//VisualFactoryCache::IMAGE_SHADER_YUV_AND_RGB,
-  "#define IS_REQUIRED_ROUNDED_CORNER\n",//VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_AND_RGB,
+constexpr std::string_view VertexPredefines[SHADER_TYPE_COUNT]{
+  "",                                     // VisualFactoryCache::IMAGE_SHADER,
+  "#define IS_REQUIRED_ROUNDED_CORNER\n", // VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER,
+  "",                                     // VisualFactoryCache::IMAGE_SHADER_YUV_TO_RGB,
+  "#define IS_REQUIRED_ROUNDED_CORNER\n", // VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_TO_RGB,
+  "",                                     // VisualFactoryCache::IMAGE_SHADER_YUV_AND_RGB,
+  "#define IS_REQUIRED_ROUNDED_CORNER\n", // VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_AND_RGB,
 };
-const std::string_view FragmentPredefines[SHADER_TYPE_COUNT]
-{
-  "", // VisualFactoryCache::IMAGE_SHADER,
-  "#define IS_REQUIRED_ROUNDED_CORNER\n", //VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER,
-  "#define IS_REQUIRED_YUV_TO_RGB\n",//VisualFactoryCache::IMAGE_SHADER_YUV_TO_RGB,
-  "#define IS_REQUIRED_YUV_TO_RGB\n#define IS_REQUIRED_ROUNDED_CORNER\n",//VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_TO_RGB,
-  "#define IS_REQUIRED_UNIFIED_YUV_AND_RGB\n",//VisualFactoryCache::IMAGE_SHADER_YUV_AND_RGB,
-  "#define IS_REQUIRED_UNIFIED_YUV_AND_RGB\n#define IS_REQUIRED_ROUNDED_CORNER\n",//VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_AND_RGB,
+constexpr std::string_view FragmentPredefines[SHADER_TYPE_COUNT]{
+  "",                                                                              // VisualFactoryCache::IMAGE_SHADER,
+  "#define IS_REQUIRED_ROUNDED_CORNER\n",                                          // VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER,
+  "#define IS_REQUIRED_YUV_TO_RGB\n",                                              // VisualFactoryCache::IMAGE_SHADER_YUV_TO_RGB,
+  "#define IS_REQUIRED_YUV_TO_RGB\n#define IS_REQUIRED_ROUNDED_CORNER\n",          // VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_TO_RGB,
+  "#define IS_REQUIRED_UNIFIED_YUV_AND_RGB\n",                                     // VisualFactoryCache::IMAGE_SHADER_YUV_AND_RGB,
+  "#define IS_REQUIRED_UNIFIED_YUV_AND_RGB\n#define IS_REQUIRED_ROUNDED_CORNER\n", // VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_AND_RGB,
 };
+} // unnamed namespace
 
 ImageVisualShaderFactory::ImageVisualShaderFactory()
 : mFragmentShaderNeedChange(ImageVisualShaderFeature::ChangeFragmentShader::UNDECIDED)
@@ -93,9 +92,20 @@ Shader ImageVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, Ima
   featureBuilder.GetVertexShaderPrefixList(vertexShaderPrefixList);
   featureBuilder.GetFragmentShaderPrefixList(fragmentShaderPrefixList);
 
+  if(Dali::Toolkit::Internal::ImageVisualShaderDebug::DebugImageVisualShaderEnabled())
+  {
+    vertexShaderPrefixList += "#define IS_REQUIRED_DEBUG_VISUAL_SHADER\n";
+    fragmentShaderPrefixList += "#define IS_REQUIRED_DEBUG_VISUAL_SHADER\n";
+  }
+
   std::string vertexShader   = std::string(Dali::Shader::GetVertexShaderPrefix() + vertexShaderPrefixList + SHADER_IMAGE_VISUAL_SHADER_VERT.data());
   std::string fragmentShader = std::string(Dali::Shader::GetFragmentShaderPrefix() + fragmentShaderPrefixList + SHADER_IMAGE_VISUAL_SHADER_FRAG.data());
 
+  if(Dali::Toolkit::Internal::ImageVisualShaderDebug::DebugImageVisualShaderEnabled())
+  {
+    Dali::Toolkit::Internal::ImageVisualShaderDebug::ApplyImageVisualShaderDebugScriptCode(fragmentShader);
+  }
+
   if(featureBuilder.NeedToChangeFragmentShader() == ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE)
   {
     bool modified = DevelTexture::ApplyNativeFragmentShader(featureBuilder.GetTexture(), fragmentShader);
@@ -159,19 +169,19 @@ void ImageVisualShaderFactory::GetPreCompiledShader(RawShaderData& shaders)
   std::vector<std::string_view> vertexPrefix;
   std::vector<std::string_view> fragmentPrefix;
   shaders.shaderCount = 0;
-  int shaderCount = 0;
-  for(uint32_t i=0; i< SHADER_TYPE_COUNT; ++i)
+  int shaderCount     = 0;
+  for(uint32_t i = 0; i < SHADER_TYPE_COUNT; ++i)
   {
     vertexPrefix.push_back(VertexPredefines[i]);
     fragmentPrefix.push_back(FragmentPredefines[i]);
     shaderCount++;
   }
 
-  shaders.vertexPrefix= vertexPrefix;
+  shaders.vertexPrefix   = vertexPrefix;
   shaders.fragmentPrefix = fragmentPrefix;
-  shaders.vertexShader = SHADER_IMAGE_VISUAL_SHADER_VERT;
+  shaders.vertexShader   = SHADER_IMAGE_VISUAL_SHADER_VERT;
   shaders.fragmentShader = SHADER_IMAGE_VISUAL_SHADER_FRAG;
-  shaders.shaderCount = shaderCount;
+  shaders.shaderCount    = shaderCount;
 }
 
 } // namespace Internal
index 3b60eda..81b4323 100644 (file)
@@ -29,7 +29,7 @@ namespace Toolkit
 {
 const unsigned int TOOLKIT_MAJOR_VERSION = 2;
 const unsigned int TOOLKIT_MINOR_VERSION = 3;
-const unsigned int TOOLKIT_MICRO_VERSION = 1;
+const unsigned int TOOLKIT_MICRO_VERSION = 2;
 const char* const  TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
diff --git a/dali-toolkit/styles/debug-image-visual-shader-script.json b/dali-toolkit/styles/debug-image-visual-shader-script.json
new file mode 100644 (file)
index 0000000..eb53e94
--- /dev/null
@@ -0,0 +1,49 @@
+//******************************************************************************
+//
+// Default debug image visual shader script for dali-toolkit
+// It will be used only if export DALI_DEBUG_IMAGE_VISUAL_SHADER=1
+//
+//******************************************************************************
+{
+  // Range of color rate for debug
+  "minimumColorRate": 0.2,
+  "maximumColorRate": "0.7",
+
+  // Logic for red. (It show if we use YUV image)
+  // We can use macro keyword was defined or not by ~~_BOOL value.
+  "redChannelCodes":
+  {
+    "triggerCode":
+    [
+      "return IS_REQUIRED_YUV_TO_RGB_BOOL;"
+    ],
+    "ratioCode": "return 1.0;"
+  },
+
+  // Logic for green. (It show if we use unified YUV and RGB shader)
+  "greenChannelCodes":
+  {
+    "triggerCode": "return IS_REQUIRED_UNIFIED_YUV_AND_RGB_BOOL;",
+    "ratioCode":
+    [
+      "return 1.0;"
+    ]
+  },
+
+  // Logic for blue. (It show when we use GPU masking)
+  // Note that we can seperate each line as array.
+  "blueChannelCodes":
+  {
+    "triggerCode":
+    [
+      "bool triggerReturn = IS_REQUIRED_ALPHA_MASKING_BOOL;",
+      "",
+      "return triggerReturn;"
+    ],
+    "ratioCode":
+    [
+      "mediump float alpha = originColor.a;",
+      "return step(0.5, alpha);"
+    ]
+  }
+}
index 2e4dd65..f60c5c3 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali2-toolkit
 Summary:    Dali 3D engine Toolkit
-Version:    2.3.1
+Version:    2.3.2
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT
@@ -262,6 +262,9 @@ cp -r dali-toolkit/styles/1920x1080_rpi/* %{buildroot}%{dali_toolkit_style_files
 
 # Copy default feedback theme
 cp dali-toolkit/styles/default-feedback-theme.json %{buildroot}%{dali_toolkit_style_files}
+
+# Copy default debug image visual shader script
+cp dali-toolkit/styles/debug-image-visual-shader-script.json %{buildroot}%{dali_toolkit_style_files}
 popd
 
 ##############################
@@ -481,6 +484,7 @@ esac
 %{dali_toolkit_image_files}/*
 %{dali_toolkit_sound_files}/*
 %{dali_toolkit_style_files}/360x360/*
+%{dali_toolkit_style_files}/debug-image-visual-shader-script.json
 %{dali_toolkit_style_files}/default-feedback-theme.json
 %{_datadir}/locale/*/LC_MESSAGES/*
 
@@ -490,6 +494,7 @@ esac
 %{dali_toolkit_image_files}/*
 %{dali_toolkit_sound_files}/*
 %{dali_toolkit_style_files}/480x800/*
+%{dali_toolkit_style_files}/debug-image-visual-shader-script.json
 %{dali_toolkit_style_files}/default-feedback-theme.json
 %{_datadir}/locale/*/LC_MESSAGES/*
 
@@ -499,6 +504,7 @@ esac
 %{dali_toolkit_image_files}/*
 %{dali_toolkit_sound_files}/*
 %{dali_toolkit_style_files}/720x1280/*
+%{dali_toolkit_style_files}/debug-image-visual-shader-script.json
 %{dali_toolkit_style_files}/default-feedback-theme.json
 %{_datadir}/locale/*/LC_MESSAGES/*
 
@@ -508,6 +514,7 @@ esac
 %{dali_toolkit_image_files}/*
 %{dali_toolkit_sound_files}/*
 %{dali_toolkit_style_files}/1920x1080/*
+%{dali_toolkit_style_files}/debug-image-visual-shader-script.json
 %{dali_toolkit_style_files}/default-feedback-theme.json
 %{_datadir}/locale/*/LC_MESSAGES/*
 
@@ -517,6 +524,7 @@ esac
 %{dali_toolkit_image_files}/*
 %{dali_toolkit_sound_files}/*
 %{dali_toolkit_style_files}/1920x1080_rpi/*
+%{dali_toolkit_style_files}/debug-image-visual-shader-script.json
 %{dali_toolkit_style_files}/default-feedback-theme.json
 %{_datadir}/locale/*/LC_MESSAGES/*