Merge "Add ImageVisualShaderFactory" into devel/master
authorHeeyong Song <heeyong.song@samsung.com>
Tue, 21 Aug 2018 00:16:38 +0000 (00:16 +0000)
committerGerrit Code Review <gerrit@review.ap-northeast-2.compute.internal>
Tue, 21 Aug 2018 00:16:38 +0000 (00:16 +0000)
14 files changed:
automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp
automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp
dali-toolkit/internal/file.list
dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp
dali-toolkit/internal/visuals/animated-image/animated-image-visual.h
dali-toolkit/internal/visuals/image-visual-shader-factory.cpp [new file with mode: 0644]
dali-toolkit/internal/visuals/image-visual-shader-factory.h [new file with mode: 0644]
dali-toolkit/internal/visuals/image/image-visual.cpp
dali-toolkit/internal/visuals/image/image-visual.h
dali-toolkit/internal/visuals/svg/svg-visual.cpp
dali-toolkit/internal/visuals/svg/svg-visual.h
dali-toolkit/internal/visuals/visual-factory-cache.h
dali-toolkit/internal/visuals/visual-factory-impl.cpp
dali-toolkit/internal/visuals/visual-factory-impl.h

index 5cbfc89..90dd9e7 100644 (file)
@@ -2104,3 +2104,77 @@ int UtcDaliImageVisualOrientationCorrection(void)
 
   END_TEST;
 }
+
+int UtcDaliImageVisualCustomShader(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline( "UtcDaliImageVisualCustomShader Test custom shader" );
+
+  VisualFactory factory = VisualFactory::Get();
+  Property::Map properties;
+  Property::Map shader;
+  const std::string vertexShader = "Foobar";
+  const std::string fragmentShader = "Foobar";
+  shader[Visual::Shader::Property::FRAGMENT_SHADER] = fragmentShader;
+  shader[Visual::Shader::Property::VERTEX_SHADER] = vertexShader;
+
+  properties[Visual::Property::TYPE] = Visual::IMAGE;
+  properties[Visual::Property::SHADER] = shader;
+  properties[ImageVisual::Property::URL] = TEST_IMAGE_FILE_NAME;
+
+  Visual::Base visual = factory.CreateVisual( properties );
+
+  // trigger creation through setting on stage
+  DummyControl dummy = DummyControl::New( true );
+  Impl::DummyControl& dummyImpl = static_cast< Impl::DummyControl& >( dummy.GetImplementation() );
+  dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+
+  dummy.SetSize( 200.f, 200.f );
+  dummy.SetParentOrigin( ParentOrigin::CENTER );
+  Stage::GetCurrent().Add( dummy );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  Renderer renderer = dummy.GetRendererAt( 0 );
+  Shader shader2 = renderer.GetShader();
+  Property::Value value = shader2.GetProperty( Shader::Property::PROGRAM );
+  Property::Map* map = value.GetMap();
+  DALI_TEST_CHECK( map );
+
+  Property::Value* fragment = map->Find( "fragment" ); // fragment key name from shader-impl.cpp
+  DALI_TEST_EQUALS( fragmentShader, fragment->Get< std::string >(), TEST_LOCATION );
+
+  Property::Value* vertex = map->Find( "vertex" ); // vertex key name from shader-impl.cpp
+  DALI_TEST_EQUALS( vertexShader, vertex->Get< std::string >(), TEST_LOCATION );
+
+  shader.Clear();
+
+  shader[Visual::Shader::Property::HINTS] = Shader::Hint::OUTPUT_IS_TRANSPARENT;
+  properties[Visual::Property::SHADER] = shader;
+
+  Visual::Base visual1 = factory.CreateVisual( properties );
+
+  // trigger creation through setting on stage
+  DummyControl dummy1 = DummyControl::New( true );
+  Impl::DummyControl& dummyImpl1 = static_cast< Impl::DummyControl& >( dummy1.GetImplementation() );
+  dummyImpl1.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual1 );
+  dummy1.SetSize( 200, 200 );
+  dummy1.SetParentOrigin( ParentOrigin::CENTER );
+  Stage::GetCurrent().Add( dummy1 );
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  glAbstraction.EnableEnableDisableCallTrace( true );
+
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack& glEnableStack = glAbstraction.GetEnableDisableTrace();
+  std::ostringstream blendStr;
+  blendStr << GL_BLEND;
+  DALI_TEST_CHECK( glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) );
+
+  END_TEST;
+}
index 07c8564..a88c763 100644 (file)
@@ -3514,3 +3514,51 @@ int UtcDaliColorVisualRenderIfTransparentProperty(void)
 
   END_TEST;
 }
+
+int UtcDaliSvgVisualCustomShader(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline( "SvgVisual with custom shader" );
+
+  VisualFactory factory = VisualFactory::Get();
+  Property::Map properties;
+  Property::Map shader;
+  const std::string vertexShader = "Foobar";
+  const std::string fragmentShader = "Foobar";
+  shader[Dali::Toolkit::Visual::Shader::Property::FRAGMENT_SHADER] = fragmentShader;
+  shader[Dali::Toolkit::Visual::Shader::Property::VERTEX_SHADER] = vertexShader;
+
+  properties[Visual::Property::TYPE] = Visual::IMAGE;
+  properties[Visual::Property::SHADER] = shader;
+  properties[ImageVisual::Property::URL] = TEST_SVG_FILE_NAME;
+
+  Visual::Base visual = factory.CreateVisual( properties );
+
+  // trigger creation through setting on stage
+  DummyControl dummy = DummyControl::New( true );
+  Impl::DummyControl& dummyImpl = static_cast< Impl::DummyControl& >( dummy.GetImplementation() );
+  dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+
+  dummy.SetSize( 200.f, 200.f );
+  dummy.SetParentOrigin( ParentOrigin::CENTER );
+  Stage::GetCurrent().Add( dummy );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  Renderer renderer = dummy.GetRendererAt( 0 );
+  Shader shader2 = renderer.GetShader();
+  Property::Value value = shader2.GetProperty( Shader::Property::PROGRAM );
+  Property::Map* map = value.GetMap();
+  DALI_TEST_CHECK( map );
+
+  Property::Value* fragment = map->Find( "fragment" ); // fragment key name from shader-impl.cpp
+  DALI_TEST_EQUALS( fragmentShader, fragment->Get< std::string >(), TEST_LOCATION );
+
+  Property::Value* vertex = map->Find( "vertex" ); // vertex key name from shader-impl.cpp
+  DALI_TEST_EQUALS( vertexShader, vertex->Get< std::string >(), TEST_LOCATION );
+
+  END_TEST;
+}
index 6475502..3f0bd91 100755 (executable)
@@ -44,6 +44,7 @@ toolkit_src_files = \
    $(toolkit_src_dir)/visuals/transition-data-impl.cpp \
    $(toolkit_src_dir)/visuals/texture-manager-impl.cpp \
    $(toolkit_src_dir)/visuals/texture-upload-observer.cpp \
+   $(toolkit_src_dir)/visuals/image-visual-shader-factory.cpp \
    $(toolkit_src_dir)/visuals/visual-base-data-impl.cpp \
    $(toolkit_src_dir)/visuals/visual-base-impl.cpp \
    $(toolkit_src_dir)/visuals/visual-factory-cache.cpp \
index fcb3811..ec58860 100755 (executable)
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
+#include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
 #include <dali-toolkit/internal/visuals/animated-image/fixed-image-cache.h>
 #include <dali-toolkit/internal/visuals/animated-image/rolling-image-cache.h>
 #include <dali-toolkit/internal/visuals/animated-image/rolling-gif-image-cache.h>
-#include <dali-toolkit/internal/visuals/image/image-visual.h>
 #include <dali-toolkit/devel-api/image-loader/image-atlas.h>
 #include <dali-toolkit/devel-api/image-loader/texture-manager.h>
+#include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
 
 namespace Dali
 {
@@ -100,9 +101,9 @@ Debug::Filter* gAnimImgLogFilter = Debug::Filter::New(Debug::NoLogging, false, "
  *  Time
  */
 
-AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, const VisualUrl& imageUrl, const Property::Map& properties )
+AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl, const Property::Map& properties )
 {
-  AnimatedImageVisualPtr visual( new AnimatedImageVisual( factoryCache ) );
+  AnimatedImageVisualPtr visual( new AnimatedImageVisual( factoryCache, shaderFactory ) );
   visual->InitializeGif( imageUrl );
   visual->SetProperties( properties );
 
@@ -114,9 +115,9 @@ AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCach
   return visual;
 }
 
-AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, const Property::Array& imageUrls, const Property::Map& properties )
+AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const Property::Array& imageUrls, const Property::Map& properties )
 {
-  AnimatedImageVisualPtr visual( new AnimatedImageVisual( factoryCache ) );
+  AnimatedImageVisualPtr visual( new AnimatedImageVisual( factoryCache, shaderFactory ) );
   visual->mImageUrls = new ImageCache::UrlList();
   visual->mImageUrls->reserve( imageUrls.Count() );
 
@@ -138,9 +139,9 @@ AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCach
   return visual;
 }
 
-AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, const VisualUrl& imageUrl )
+AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl )
 {
-  AnimatedImageVisualPtr visual( new AnimatedImageVisual( factoryCache ) );
+  AnimatedImageVisualPtr visual( new AnimatedImageVisual( factoryCache, shaderFactory ) );
   visual->InitializeGif( imageUrl );
 
   if( visual->mFrameCount > 0 )
@@ -159,10 +160,11 @@ void AnimatedImageVisual::InitializeGif( const VisualUrl& imageUrl )
   mGifLoading->LoadFrameDelays( mFrameDelayContainer );
 }
 
-AnimatedImageVisual::AnimatedImageVisual( VisualFactoryCache& factoryCache )
+AnimatedImageVisual::AnimatedImageVisual( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory )
 : Visual::Base( factoryCache, Visual::FittingMode::FIT_KEEP_ASPECT_RATIO ),
   mFrameDelayTimer(),
   mPlacementActor(),
+  mImageVisualShaderFactory( shaderFactory ),
   mPixelArea( FULL_TEXTURE_RECT ),
   mImageUrl(),
   mGifLoading( nullptr ),
@@ -442,7 +444,7 @@ void AnimatedImageVisual::CreateRenderer()
 {
   bool defaultWrapMode = mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE;
   bool atlasing = false;
-  Shader shader = ImageVisual::GetImageShader( mFactoryCache, atlasing, defaultWrapMode );
+  Shader shader = mImageVisualShaderFactory.GetShader( mFactoryCache, atlasing, defaultWrapMode );
 
   Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY );
 
index 0db9154..b5fbb2e 100644 (file)
@@ -41,6 +41,7 @@ namespace Toolkit
 namespace Internal
 {
 
+class ImageVisualShaderFactory;
 class AnimatedImageVisual;
 typedef IntrusivePtr< AnimatedImageVisual > AnimatedImageVisualPtr;
 
@@ -90,29 +91,32 @@ public:
    * @brief Create the animated image Visual using the image URL.
    *
    * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object
+   * @param[in] shaderFactory The ImageVisualShaderFactory object
    * @param[in] imageUrl The URL to gif resource to use
    * @param[in] properties A Property::Map containing settings for this visual
    * @return A smart-pointer to the newly allocated visual.
    */
-  static AnimatedImageVisualPtr New( VisualFactoryCache& factoryCache, const VisualUrl& imageUrl, const Property::Map& properties );
+  static AnimatedImageVisualPtr New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl, const Property::Map& properties );
 
   /**
    * @brief Create the animated image Visual using image URLs.
    *
    * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object
+   * @param[in] shaderFactory The ImageVisualShaderFactory object
    * @param[in] imageUrls A Property::Array containing the URLs to the image resources
    * @param[in] properties A Property::Map containing settings for this visual
    * @return A smart-pointer to the newly allocated visual.
    */
-  static AnimatedImageVisualPtr New( VisualFactoryCache& factoryCache, const Property::Array& imageUrls, const Property::Map& properties );
+  static AnimatedImageVisualPtr New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const Property::Array& imageUrls, const Property::Map& properties );
 
   /**
    * @brief Create the animated image visual using the image URL.
    *
    * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object
+   * @param[in] shaderFactory The ImageVisualShaderFactory object
    * @param[in] imageUrl The URL to animated image resource to use
    */
-  static AnimatedImageVisualPtr New( VisualFactoryCache& factoryCache, const VisualUrl& imageUrl );
+  static AnimatedImageVisualPtr New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl );
 
 public:  // from Visual
 
@@ -142,8 +146,9 @@ protected:
    * @brief Constructor.
    *
    * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object
+   * @param[in] shaderFactory The ImageVisualShaderFactory object
    */
-  AnimatedImageVisual( VisualFactoryCache& factoryCache );
+  AnimatedImageVisual( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory );
 
   /**
    * @brief A reference counted object may only be deleted by calling Unreference().
@@ -234,6 +239,7 @@ private:
 
   Timer mFrameDelayTimer;
   WeakHandle<Actor> mPlacementActor;
+  ImageVisualShaderFactory& mImageVisualShaderFactory;
 
   // Variables for GIF player
   Dali::Vector<uint32_t> mFrameDelayContainer;
diff --git a/dali-toolkit/internal/visuals/image-visual-shader-factory.cpp b/dali-toolkit/internal/visuals/image-visual-shader-factory.cpp
new file mode 100644 (file)
index 0000000..3c3fc30
--- /dev/null
@@ -0,0 +1,194 @@
+ /*
+ * Copyright (c) 2018 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-factory.h>
+
+// EXTERNAL INCLUDES
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/visuals/visual-string-constants.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
+
+const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
+  attribute mediump vec2 aPosition;\n
+  uniform mediump mat4 uModelMatrix;\n
+  uniform mediump mat4 uViewMatrix;\n
+  uniform mediump mat4 uProjection;\n
+  uniform mediump vec3 uSize;\n
+  uniform mediump vec4 pixelArea;
+  varying mediump vec2 vTexCoord;\n
+  uniform lowp float uPixelAligned;\n
+  \n
+  //Visual size and offset
+  uniform mediump vec2 offset;\n
+  uniform mediump vec2 size;\n
+  uniform mediump vec4 offsetSizeMode;\n
+  uniform mediump vec2 origin;\n
+  uniform mediump vec2 anchorPoint;\n
+\n
+  vec4 ComputeVertexPosition()\n
+  {\n
+    vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw );\n
+    vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);\n
+    return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );\n
+  }\n
+\n
+  void main()\n
+  {\n
+    mediump vec4 vertexPosition = uViewMatrix * uModelMatrix * ComputeVertexPosition();\n
+    vec4 alignedVertexPosition = vertexPosition;\n
+    alignedVertexPosition.xy = floor ( vertexPosition.xy );\n // Pixel alignment
+    vertexPosition = uProjection * mix( vertexPosition, alignedVertexPosition, uPixelAligned );\n
+    vTexCoord = pixelArea.xy+pixelArea.zw*(aPosition + vec2(0.5) );\n
+    gl_Position = vertexPosition;\n
+  }\n
+);
+
+const char* FRAGMENT_SHADER_NO_ATLAS = DALI_COMPOSE_SHADER(
+  varying mediump vec2 vTexCoord;\n
+  uniform sampler2D sTexture;\n
+  uniform lowp vec4 uColor;\n
+  uniform lowp vec3 mixColor;\n
+  uniform lowp float preMultipliedAlpha;\n
+  \n
+  void main()\n
+  {\n
+      gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor * vec4( mixColor, 1.0 );\n
+  }\n
+);
+
+const char* FRAGMENT_SHADER_ATLAS_CLAMP = DALI_COMPOSE_SHADER(
+    varying mediump vec2 vTexCoord;\n
+    uniform sampler2D sTexture;\n
+    uniform mediump vec4 uAtlasRect;\n
+    uniform lowp vec4 uColor;\n
+    uniform lowp vec3 mixColor;\n
+    uniform lowp float preMultipliedAlpha;\n
+    \n
+    void main()\n
+    {\n
+        mediump vec2 texCoord = clamp( mix( uAtlasRect.xy, uAtlasRect.zw, vTexCoord ), uAtlasRect.xy, uAtlasRect.zw );\n
+        gl_FragColor = texture2D( sTexture, texCoord ) * uColor * vec4( mixColor, 1.0 );\n
+     }\n
+);
+
+const char* FRAGMENT_SHADER_ATLAS_VARIOUS_WRAP = DALI_COMPOSE_SHADER(
+    varying mediump vec2 vTexCoord;\n
+    uniform sampler2D sTexture;\n
+    uniform mediump vec4 uAtlasRect;\n
+    // WrapMode -- 0: CLAMP; 1: REPEAT; 2: REFLECT;
+    uniform lowp vec2 wrapMode;\n
+    uniform lowp vec4 uColor;\n
+    uniform lowp vec3 mixColor;\n
+    uniform lowp float preMultipliedAlpha;\n
+    \n
+    mediump float wrapCoordinate( mediump vec2 range, mediump float coordinate, lowp float wrap )\n
+    {\n
+      mediump float coord;\n
+      if( wrap > 1.5 )\n // REFLECT
+        coord = 1.0-abs(fract(coordinate*0.5)*2.0 - 1.0);\n
+      else \n// warp == 0 or 1
+        coord = mix(coordinate, fract( coordinate ), wrap);\n
+      return clamp( mix(range.x, range.y, coord), range.x, range.y );
+    }\n
+    \n
+    void main()\n
+    {\n
+        mediump vec2 texCoord = vec2( wrapCoordinate( uAtlasRect.xz, vTexCoord.x, wrapMode.x ),
+                                      wrapCoordinate( uAtlasRect.yw, vTexCoord.y, wrapMode.y ) );\n
+        gl_FragColor = texture2D( sTexture, texCoord ) * uColor * vec4( mixColor, 1.0 );\n
+    }\n
+);
+
+} // unnamed namespace
+
+ImageVisualShaderFactory::ImageVisualShaderFactory()
+{
+}
+
+ImageVisualShaderFactory::~ImageVisualShaderFactory()
+{
+}
+
+Shader ImageVisualShaderFactory::GetShader( VisualFactoryCache& factoryCache, bool atlasing, bool defaultTextureWrapping )
+{
+  Shader shader;
+  if( atlasing )
+  {
+    if( defaultTextureWrapping )
+    {
+      shader = factoryCache.GetShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP );
+      if( !shader )
+      {
+        shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_ATLAS_CLAMP );
+        shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
+        factoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP, shader );
+      }
+    }
+    else
+    {
+      shader = factoryCache.GetShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_CUSTOM_WRAP );
+      if( !shader )
+      {
+        shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_ATLAS_VARIOUS_WRAP );
+        shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
+        factoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_CUSTOM_WRAP, shader );
+      }
+    }
+  }
+  else
+  {
+    shader = factoryCache.GetShader( VisualFactoryCache::IMAGE_SHADER );
+    if( !shader )
+    {
+      shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_NO_ATLAS );
+      shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
+      factoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER, shader );
+    }
+  }
+
+  return shader;
+}
+
+const char* ImageVisualShaderFactory::GetVertexShaderSource()
+{
+  return VERTEX_SHADER;
+}
+
+const char* ImageVisualShaderFactory::GetFragmentShaderSource()
+{
+  return FRAGMENT_SHADER_NO_ATLAS;
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/image-visual-shader-factory.h b/dali-toolkit/internal/visuals/image-visual-shader-factory.h
new file mode 100644 (file)
index 0000000..58b4dd0
--- /dev/null
@@ -0,0 +1,94 @@
+#ifndef DALI_TOOLKIT_IMAGE_VISUAL_SHADER_FACTORY_H
+#define DALI_TOOLKIT_IMAGE_VISUAL_SHADER_FACTORY_H
+
+/*
+ * Copyright (c) 2018 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
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/visuals/visual-factory-cache.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+/**
+ * ImageVisualShaderFactory is an object that provides and shares shaders between image visuals
+ */
+class ImageVisualShaderFactory
+{
+public:
+
+public:
+
+  /**
+   * @brief Constructor
+   */
+  ImageVisualShaderFactory();
+
+  /**
+   * @brief Destructor
+   */
+  ~ImageVisualShaderFactory();
+
+  /**
+   * Get the standard image rendering shader.
+   * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object
+   * @param[in] atlasing Whether texture atlasing is applied.
+   * @param[in] defaultTextureWrapping Whether the default texture wrap mode is applied.
+   */
+  Shader GetShader( VisualFactoryCache& factoryCache, bool atlasing, bool defaultTextureWrapping );
+
+  /**
+   * Request the default vertex shader source.
+   * @return The default vertex shader source.
+   */
+  const char* GetVertexShaderSource();
+
+  /**
+   * Request the default fragment shader source.
+   * @return The default fragment shader source.
+   */
+  const char* GetFragmentShaderSource();
+
+protected:
+
+  /**
+   * Undefined copy constructor.
+   */
+  ImageVisualShaderFactory(const ImageVisualShaderFactory&);
+
+  /**
+   * Undefined assignment operator.
+   */
+  ImageVisualShaderFactory& operator=(const ImageVisualShaderFactory& rhs);
+
+private:
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_IMAGE_VISUAL_SHADER_FACTORY_H
index 2fb7e5d..3f4e763 100644 (file)
@@ -42,6 +42,7 @@
 #include <dali-toolkit/internal/visuals/image-atlas-manager.h>
 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
 #include <dali-toolkit/internal/visuals/visual-url.h>
+#include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
 
 namespace Dali
 {
@@ -112,97 +113,6 @@ const char* DEFAULT_SAMPLER_TYPENAME = "sampler2D";
 const float PIXEL_ALIGN_ON = 1.0f;
 const float PIXEL_ALIGN_OFF = 0.0f;
 
-const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
-  attribute mediump vec2 aPosition;\n
-  uniform mediump mat4 uModelMatrix;\n
-  uniform mediump mat4 uViewMatrix;\n
-  uniform mediump mat4 uProjection;\n
-  uniform mediump vec3 uSize;\n
-  uniform mediump vec4 pixelArea;
-  varying mediump vec2 vTexCoord;\n
-  uniform lowp float uPixelAligned;\n
-  \n
-  //Visual size and offset
-  uniform mediump vec2 offset;\n
-  uniform mediump vec2 size;\n
-  uniform mediump vec4 offsetSizeMode;\n
-  uniform mediump vec2 origin;\n
-  uniform mediump vec2 anchorPoint;\n
-\n
-  vec4 ComputeVertexPosition()\n
-  {\n
-    vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw );\n
-    vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);\n
-    return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );\n
-  }\n
-\n
-  void main()\n
-  {\n
-    mediump vec4 vertexPosition = uViewMatrix * uModelMatrix * ComputeVertexPosition();\n
-    vec4 alignedVertexPosition = vertexPosition;\n
-    alignedVertexPosition.xy = floor ( vertexPosition.xy );\n // Pixel alignment
-    vertexPosition = uProjection * mix( vertexPosition, alignedVertexPosition, uPixelAligned );\n
-    vTexCoord = pixelArea.xy+pixelArea.zw*(aPosition + vec2(0.5) );\n
-    gl_Position = vertexPosition;\n
-  }\n
-);
-
-const char* FRAGMENT_SHADER_NO_ATLAS = DALI_COMPOSE_SHADER(
-  varying mediump vec2 vTexCoord;\n
-  uniform sampler2D sTexture;\n
-  uniform lowp vec4 uColor;\n
-  uniform lowp vec3 mixColor;\n
-  uniform lowp float preMultipliedAlpha;\n
-  \n
-  void main()\n
-  {\n
-      gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor * vec4( mixColor, 1.0 );\n
-  }\n
-);
-
-const char* FRAGMENT_SHADER_ATLAS_CLAMP = DALI_COMPOSE_SHADER(
-    varying mediump vec2 vTexCoord;\n
-    uniform sampler2D sTexture;\n
-    uniform mediump vec4 uAtlasRect;\n
-    uniform lowp vec4 uColor;\n
-    uniform lowp vec3 mixColor;\n
-    uniform lowp float preMultipliedAlpha;\n
-    \n
-    void main()\n
-    {\n
-        mediump vec2 texCoord = clamp( mix( uAtlasRect.xy, uAtlasRect.zw, vTexCoord ), uAtlasRect.xy, uAtlasRect.zw );\n
-        gl_FragColor = texture2D( sTexture, texCoord ) * uColor * vec4( mixColor, 1.0 );\n
-     }\n
-);
-
-const char* FRAGMENT_SHADER_ATLAS_VARIOUS_WRAP = DALI_COMPOSE_SHADER(
-    varying mediump vec2 vTexCoord;\n
-    uniform sampler2D sTexture;\n
-    uniform mediump vec4 uAtlasRect;\n
-    // WrapMode -- 0: CLAMP; 1: REPEAT; 2: REFLECT;
-    uniform lowp vec2 wrapMode;\n
-    uniform lowp vec4 uColor;\n
-    uniform lowp vec3 mixColor;\n
-    uniform lowp float preMultipliedAlpha;\n
-    \n
-    mediump float wrapCoordinate( mediump vec2 range, mediump float coordinate, lowp float wrap )\n
-    {\n
-      mediump float coord;\n
-      if( wrap > 1.5 )\n // REFLECT
-        coord = 1.0-abs(fract(coordinate*0.5)*2.0 - 1.0);\n
-      else \n// warp == 0 or 1
-        coord = mix(coordinate, fract( coordinate ), wrap);\n
-      return clamp( mix(range.x, range.y, coord), range.x, range.y );
-    }\n
-    \n
-    void main()\n
-    {\n
-        mediump vec2 texCoord = vec2( wrapCoordinate( uAtlasRect.xz, vTexCoord.x, wrapMode.x ),
-                                      wrapCoordinate( uAtlasRect.yw, vTexCoord.y, wrapMode.y ) );\n
-        gl_FragColor = texture2D( sTexture, texCoord ) * uColor * vec4( mixColor, 1.0 );\n
-    }\n
-);
-
 Geometry CreateGeometry( VisualFactoryCache& factoryCache, ImageDimensions gridSize )
 {
   Geometry geometry;
@@ -222,32 +132,35 @@ Geometry CreateGeometry( VisualFactoryCache& factoryCache, ImageDimensions gridS
 } // unnamed namespace
 
 ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache,
+                                 ImageVisualShaderFactory& shaderFactory,
                                  const VisualUrl& imageUrl,
                                  const Property::Map& properties,
                                  ImageDimensions size,
                                  FittingMode::Type fittingMode,
                                  Dali::SamplingMode::Type samplingMode )
 {
-  ImageVisualPtr imageVisualPtr( new ImageVisual( factoryCache, imageUrl, size, fittingMode, samplingMode ) );
+  ImageVisualPtr imageVisualPtr( new ImageVisual( factoryCache, shaderFactory, imageUrl, size, fittingMode, samplingMode ) );
   imageVisualPtr->SetProperties( properties );
   return imageVisualPtr;
 }
 
 ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache,
+                                 ImageVisualShaderFactory& shaderFactory,
                                  const VisualUrl& imageUrl,
                                  ImageDimensions size,
                                  FittingMode::Type fittingMode,
                                  Dali::SamplingMode::Type samplingMode )
 {
-  return new ImageVisual( factoryCache, imageUrl, size, fittingMode, samplingMode );
+  return new ImageVisual( factoryCache, shaderFactory, imageUrl, size, fittingMode, samplingMode );
 }
 
-ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache, const Image& image )
+ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const Image& image )
 {
-  return new ImageVisual( factoryCache, image );
+  return new ImageVisual( factoryCache, shaderFactory, image );
 }
 
 ImageVisual::ImageVisual( VisualFactoryCache& factoryCache,
+                          ImageVisualShaderFactory& shaderFactory,
                           const VisualUrl& imageUrl,
                           ImageDimensions size,
                           FittingMode::Type fittingMode,
@@ -261,6 +174,7 @@ ImageVisual::ImageVisual( VisualFactoryCache& factoryCache,
   mDesiredSize( size ),
   mTextureId( TextureManager::INVALID_TEXTURE_ID ),
   mTextures(),
+  mImageVisualShaderFactory( shaderFactory ),
   mFittingMode( fittingMode ),
   mSamplingMode( samplingMode ),
   mWrapModeU( WrapMode::DEFAULT ),
@@ -275,7 +189,7 @@ ImageVisual::ImageVisual( VisualFactoryCache& factoryCache,
 {
 }
 
-ImageVisual::ImageVisual( VisualFactoryCache& factoryCache, const Image& image )
+ImageVisual::ImageVisual( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const Image& image )
 : Visual::Base( factoryCache, Visual::FittingMode::FIT_KEEP_ASPECT_RATIO ),
   mImage( image ),
   mPixelArea( FULL_TEXTURE_RECT ),
@@ -285,6 +199,7 @@ ImageVisual::ImageVisual( VisualFactoryCache& factoryCache, const Image& image )
   mDesiredSize(),
   mTextureId( TextureManager::INVALID_TEXTURE_ID ),
   mTextures(),
+  mImageVisualShaderFactory( shaderFactory ),
   mFittingMode( FittingMode::DEFAULT ),
   mSamplingMode( SamplingMode::DEFAULT ),
   mWrapModeU( WrapMode::DEFAULT ),
@@ -651,7 +566,7 @@ void ImageVisual::CreateRenderer( TextureSet& textureSet )
   {
     geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) );
 
-    shader = GetImageShader( mFactoryCache,
+    shader = mImageVisualShaderFactory.GetShader( mFactoryCache,
                              mImpl->mFlags & Impl::IS_ATLASING_APPLIED,
                              mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE );
   }
@@ -660,13 +575,15 @@ void ImageVisual::CreateRenderer( TextureSet& textureSet )
     geometry = CreateGeometry( mFactoryCache, mImpl->mCustomShader->mGridSize );
     if( mImpl->mCustomShader->mVertexShader.empty() && mImpl->mCustomShader->mFragmentShader.empty() )
     {
-      shader = GetImageShader( mFactoryCache, false, true );
+      // Use custom hints
+      shader = Shader::New( mImageVisualShaderFactory.GetVertexShaderSource(), mImageVisualShaderFactory.GetFragmentShaderSource(), mImpl->mCustomShader->mHints );
+      shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
     }
     else
     {
-      shader  = Shader::New( mImpl->mCustomShader->mVertexShader.empty() ? VERTEX_SHADER : mImpl->mCustomShader->mVertexShader,
-                             mImpl->mCustomShader->mFragmentShader.empty() ? FRAGMENT_SHADER_NO_ATLAS : mImpl->mCustomShader->mFragmentShader,
-                             mImpl->mCustomShader->mHints );
+      shader = Shader::New( mImpl->mCustomShader->mVertexShader.empty() ? mImageVisualShaderFactory.GetVertexShaderSource() : mImpl->mCustomShader->mVertexShader,
+                            mImpl->mCustomShader->mFragmentShader.empty() ? mImageVisualShaderFactory.GetFragmentShaderSource() : mImpl->mCustomShader->mFragmentShader,
+                            mImpl->mCustomShader->mHints );
       if( mImpl->mCustomShader->mVertexShader.empty() )
       {
         shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
@@ -713,7 +630,7 @@ void ImageVisual::CreateNativeImageRenderer( NativeImage& nativeImage )
   }
   else
   {
-    fragmentShader += FRAGMENT_SHADER_NO_ATLAS;
+    fragmentShader += mImageVisualShaderFactory.GetFragmentShaderSource();
   }
 
   if( customSamplerTypename )
@@ -725,13 +642,13 @@ void ImageVisual::CreateNativeImageRenderer( NativeImage& nativeImage )
   {
     geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) );
 
-    shader  = Shader::New( VERTEX_SHADER, fragmentShader );
+    shader  = Shader::New( mImageVisualShaderFactory.GetVertexShaderSource(), fragmentShader );
     shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
   }
   else
   {
     geometry = CreateGeometry( mFactoryCache, mImpl->mCustomShader->mGridSize );
-    shader  = Shader::New( mImpl->mCustomShader->mVertexShader.empty() ? VERTEX_SHADER : mImpl->mCustomShader->mVertexShader,
+    shader  = Shader::New( mImpl->mCustomShader->mVertexShader.empty() ? mImageVisualShaderFactory.GetVertexShaderSource() : mImpl->mCustomShader->mVertexShader,
                            fragmentShader,
                            mImpl->mCustomShader->mHints );
     if( mImpl->mCustomShader->mVertexShader.empty() )
@@ -998,46 +915,6 @@ bool ImageVisual::IsResourceReady() const
            mImpl->mResourceStatus == Toolkit::Visual::ResourceStatus::FAILED );
 }
 
-Shader ImageVisual::GetImageShader( VisualFactoryCache& factoryCache, bool atlasing, bool defaultTextureWrapping )
-{
-  Shader shader;
-  if( atlasing )
-  {
-    if( defaultTextureWrapping )
-    {
-      shader = factoryCache.GetShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP );
-      if( !shader )
-      {
-        shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_ATLAS_CLAMP );
-        shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
-        factoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP, shader );
-      }
-    }
-    else
-    {
-      shader = factoryCache.GetShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_CUSTOM_WRAP );
-      if( !shader )
-      {
-        shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_ATLAS_VARIOUS_WRAP );
-        shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
-        factoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_CUSTOM_WRAP, shader );
-      }
-    }
-  }
-  else
-  {
-    shader = factoryCache.GetShader( VisualFactoryCache::IMAGE_SHADER );
-    if( !shader )
-    {
-      shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_NO_ATLAS );
-      shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
-      factoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER, shader );
-    }
-  }
-
-  return shader;
-}
-
 void ImageVisual::ApplyImageToSampler( const Image& image )
 {
   if( image )
index dd63c16..c693f0b 100644 (file)
@@ -46,6 +46,7 @@ namespace Toolkit
 namespace Internal
 {
 
+class ImageVisualShaderFactory;
 class ImageVisual;
 typedef IntrusivePtr< ImageVisual > ImageVisualPtr;
 
@@ -121,6 +122,7 @@ public:
    * The visual will load the Image asynchronously when the associated actor is put on stage, and destroy the image when it is off stage
    *
    * @param[in] factoryCache The VisualFactoryCache object
+   * @param[in] shaderFactory The ImageVisualShaderFactory object
    * @param[in] imageUrl The URL of the image resource to use
    * @param[in] properties A Property::Map containing settings for this visual
    * @param[in] size The width and height to fit the loaded image to.
@@ -129,6 +131,7 @@ public:
    * @return A smart-pointer to the newly allocated visual.
    */
   static ImageVisualPtr New( VisualFactoryCache& factoryCache,
+                             ImageVisualShaderFactory& shaderFactory,
                              const VisualUrl& imageUrl,
                              const Property::Map& properties,
                              ImageDimensions size = ImageDimensions(),
@@ -141,6 +144,7 @@ public:
    * The visual will load the Image asynchronously when the associated actor is put on stage, and destroy the image when it is off stage
    *
    * @param[in] factoryCache The VisualFactoryCache object
+   * @param[in] shaderFactory The ImageVisualShaderFactory object
    * @param[in] imageUrl The URL of the image resource to use
    * @param[in] size The width and height to fit the loaded image to.
    * @param[in] fittingMode The FittingMode of the resource to load
@@ -148,6 +152,7 @@ public:
    * @return A smart-pointer to the newly allocated visual.
    */
   static ImageVisualPtr New( VisualFactoryCache& factoryCache,
+                             ImageVisualShaderFactory& shaderFactory,
                              const VisualUrl& imageUrl,
                              ImageDimensions size = ImageDimensions(),
                              FittingMode::Type fittingMode = FittingMode::DEFAULT,
@@ -157,9 +162,10 @@ public:
    * @brief Create a new image visual with an Image type.
    *
    * @param[in] factoryCache The VisualFactoryCache object
+   * @param[in] shaderFactory The ImageVisualShaderFactory object
    * @param[in] image The image to use
    */
-  static ImageVisualPtr New( VisualFactoryCache& factoryCache, const Image& image );
+  static ImageVisualPtr New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const Image& image );
 
 public:  // from Visual
 
@@ -191,12 +197,14 @@ protected:
    * The visual will load the Image asynchronously when the associated actor is put on stage, and destroy the image when it is off stage
    *
    * @param[in] factoryCache The VisualFactoryCache object
+   * @param[in] shaderFactory The ImageVisualShaderFactory object
    * @param[in] imageUrl The URL of the image resource to use
    * @param[in] size The width and height to fit the loaded image to.
    * @param[in] fittingMode The FittingMode of the resource to load
    * @param[in] samplingMode The SamplingMode of the resource to load
    */
   ImageVisual( VisualFactoryCache& factoryCache,
+               ImageVisualShaderFactory& shaderFactory,
                const VisualUrl& imageUrl,
                ImageDimensions size,
                FittingMode::Type fittingMode,
@@ -206,9 +214,10 @@ protected:
    * @brief Constructor with an Image type.
    *
    * @param[in] factoryCache The VisualFactoryCache object
+   * @param[in] shaderFactory The ImageVisualShaderFactory object
    * @param[in] image The image to use
    */
-  ImageVisual( VisualFactoryCache& factoryCache, const Image& image );
+  ImageVisual( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const Image& image );
 
   /**
    * @brief A reference counted object may only be deleted by calling Unreference().
@@ -243,14 +252,6 @@ protected:
 public:
 
   /**
-   * Get the standard image rendering shader.
-   * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object
-   * @param[in] atlasing Whether texture atlasing is applied.
-   * @param[in] defaultTextureWrapping Whether the default texture wrap mode is applied.
-   */
-  static Shader GetImageShader( VisualFactoryCache& factoryCache, bool atlasing, bool defaultTextureWrapping );
-
-  /**
    * @copydoc AtlasUploadObserver::UploadCompleted
    *
    * To avoid rendering garbage pixels, renderer should be added to actor after the resources are ready.
@@ -367,6 +368,8 @@ private:
   TextureManager::TextureId mTextureId;
   TextureSet mTextures;
 
+  ImageVisualShaderFactory& mImageVisualShaderFactory;
+
   Dali::FittingMode::Type mFittingMode:3;
   Dali::SamplingMode::Type mSamplingMode:4;
   Dali::WrapMode::Type mWrapModeU:3;
index bf7641d..f59901c 100644 (file)
 #include <dali-toolkit/public-api/visuals/visual-properties.h>
 #include <dali-toolkit/third-party/nanosvg/nanosvg.h>
 #include <dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h>
-#include <dali-toolkit/internal/visuals/image/image-visual.h>
 #include <dali-toolkit/internal/visuals/image-atlas-manager.h>
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
-
+#include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
 
 namespace
 {
@@ -56,25 +55,26 @@ namespace Toolkit
 namespace Internal
 {
 
-SvgVisualPtr SvgVisual::New( VisualFactoryCache& factoryCache, const VisualUrl& imageUrl, const Property::Map& properties )
+SvgVisualPtr SvgVisual::New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl, const Property::Map& properties )
 {
-  SvgVisualPtr svgVisual( new SvgVisual( factoryCache ) );
+  SvgVisualPtr svgVisual( new SvgVisual( factoryCache, shaderFactory ) );
   svgVisual->ParseFromUrl( imageUrl );
   svgVisual->SetProperties( properties );
 
   return svgVisual;
 }
 
-SvgVisualPtr SvgVisual::New( VisualFactoryCache& factoryCache, const VisualUrl& imageUrl )
+SvgVisualPtr SvgVisual::New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl )
 {
-  SvgVisualPtr svgVisual( new SvgVisual( factoryCache ) );
+  SvgVisualPtr svgVisual( new SvgVisual( factoryCache, shaderFactory ) );
   svgVisual->ParseFromUrl( imageUrl );
 
   return svgVisual;
 }
 
-SvgVisual::SvgVisual( VisualFactoryCache& factoryCache )
+SvgVisual::SvgVisual( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory )
 : Visual::Base( factoryCache, Visual::FittingMode::FILL ),
+  mImageVisualShaderFactory( shaderFactory ),
   mAtlasRect( FULL_TEXTURE_RECT ),
   mImageUrl( ),
   mParsedImage( NULL ),
@@ -125,7 +125,20 @@ void SvgVisual::DoSetProperty( Property::Index index, const Property::Value& val
 
 void SvgVisual::DoSetOnStage( Actor& actor )
 {
-  Shader shader = ImageVisual::GetImageShader( mFactoryCache, mAttemptAtlasing, true );
+  Shader shader;
+  if( !mImpl->mCustomShader )
+  {
+    shader = mImageVisualShaderFactory.GetShader( mFactoryCache, mAttemptAtlasing, true );
+  }
+  else
+  {
+    shader = Shader::New( mImpl->mCustomShader->mVertexShader.empty() ? mImageVisualShaderFactory.GetVertexShaderSource() : mImpl->mCustomShader->mVertexShader,
+                          mImpl->mCustomShader->mFragmentShader.empty() ? mImageVisualShaderFactory.GetFragmentShaderSource() : mImpl->mCustomShader->mFragmentShader,
+                          mImpl->mCustomShader->mHints );
+
+    shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
+  }
+
   Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY );
   TextureSet textureSet = TextureSet::New();
   mImpl->mRenderer = Renderer::New( geometry, shader );
@@ -219,7 +232,7 @@ void SvgVisual::ApplyRasterizedImage( PixelData rasterizedPixelData )
 
     TextureSet textureSet;
 
-    if( mAttemptAtlasing )
+    if( mAttemptAtlasing && !mImpl->mCustomShader )
     {
       Vector4 atlasRect;
       textureSet = mFactoryCache.GetAtlasManager()->Add(atlasRect, rasterizedPixelData );
index 7852bfc..e516186 100644 (file)
@@ -37,6 +37,7 @@ namespace Toolkit
 namespace Internal
 {
 
+class ImageVisualShaderFactory;
 class SvgVisual;
 typedef IntrusivePtr< SvgVisual > SvgVisualPtr;
 
@@ -61,11 +62,12 @@ public:
    * And rasterize it into BufferImage synchronously when the associated actor is put on stage, and destroy the BufferImage when it is off stage
    *
    * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object
+   * @param[in] shaderFactory The ImageVisualShaderFactory object
    * @param[in] imageUrl The URL to svg resource to use
    * @param[in] properties A Property::Map containing settings for this visual
    * @return A smart-pointer to the newly allocated visual.
    */
-  static SvgVisualPtr New( VisualFactoryCache& factoryCache, const VisualUrl& imageUrl, const Property::Map& properties );
+  static SvgVisualPtr New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl, const Property::Map& properties );
 
   /**
    * @brief Create the SVG Visual using the image URL.
@@ -74,10 +76,11 @@ public:
    * And rasterize it into BufferImage synchronously when the associated actor is put on stage, and destroy the BufferImage when it is off stage
    *
    * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object
+   * @param[in] shaderFactory The ImageVisualShaderFactory object
    * @param[in] imageUrl The URL to svg resource to use
    * @return A smart-pointer to the newly allocated visual.
    */
-  static SvgVisualPtr New( VisualFactoryCache& factoryCache, const VisualUrl& imageUrl );
+  static SvgVisualPtr New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl );
 
 public:  // from Visual
 
@@ -102,8 +105,9 @@ protected:
    * @brief Constructor.
    *
    * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object
+   * @param[in] shaderFactory The ImageVisualShaderFactory object
    */
-  SvgVisual( VisualFactoryCache& factoryCache );
+  SvgVisual( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory );
 
   /**
    * @brief A reference counted object may only be deleted by calling Unreference().
@@ -170,12 +174,13 @@ private:
   SvgVisual& operator=( const SvgVisual& svgRenderer );
 
 private:
-  Vector4              mAtlasRect;
-  VisualUrl            mImageUrl;
-  NSVGimage*           mParsedImage;
-  WeakHandle<Actor>    mPlacementActor;
-  Vector2              mVisualSize;
-  bool                 mAttemptAtlasing;  ///< If true will attempt atlasing, otherwise create unique texture
+  ImageVisualShaderFactory& mImageVisualShaderFactory;
+  Vector4                   mAtlasRect;
+  VisualUrl                 mImageUrl;
+  NSVGimage*                mParsedImage;
+  WeakHandle<Actor>         mPlacementActor;
+  Vector2                   mVisualSize;
+  bool                      mAttemptAtlasing;  ///< If true will attempt atlasing, otherwise create unique texture
 };
 
 } // namespace Internal
index a62dfb4..f2c8120 100644 (file)
@@ -68,7 +68,6 @@ public:
     IMAGE_SHADER_ATLAS_CUSTOM_WRAP,
     NINE_PATCH_SHADER,
     NINE_PATCH_MASK_SHADER,
-    SVG_SHADER,
     TEXT_SHADER_MULTI_COLOR_TEXT,
     TEXT_SHADER_MULTI_COLOR_TEXT_WITH_STYLE,
     TEXT_SHADER_SINGLE_COLOR_TEXT,
index e762b3e..4afade9 100644 (file)
@@ -45,6 +45,7 @@
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
 #include <dali-toolkit/internal/visuals/visual-url.h>
 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
+#include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
 
 namespace Dali
 {
@@ -73,6 +74,7 @@ const char * const  BROKEN_IMAGE_URL( DALI_IMAGE_DIR "broken.png" ); ///< URL Fo
 
 VisualFactory::VisualFactory( bool debugEnabled )
 : mFactoryCache(),
+  mImageVisualShaderFactory(),
   mSlotDelegate(this),
   mDebugEnabled( debugEnabled ),
   mPreMultiplyOnLoad( true )
@@ -151,17 +153,17 @@ Toolkit::Visual::Base VisualFactory::CreateVisual( const Property::Map& property
               }
               case VisualUrl::SVG:
               {
-                visualPtr = SvgVisual::New( GetFactoryCache(), visualUrl, propertyMap );
+                visualPtr = SvgVisual::New( GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl, propertyMap );
                 break;
               }
               case VisualUrl::GIF:
               {
-                visualPtr = AnimatedImageVisual::New( GetFactoryCache(), visualUrl, propertyMap );
+                visualPtr = AnimatedImageVisual::New( GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl, propertyMap );
                 break;
               }
               case VisualUrl::REGULAR_IMAGE:
               {
-                visualPtr = ImageVisual::New( GetFactoryCache(), visualUrl, propertyMap );
+                visualPtr = ImageVisual::New( GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl, propertyMap );
                 break;
               }
             }
@@ -172,7 +174,7 @@ Toolkit::Visual::Base VisualFactory::CreateVisual( const Property::Map& property
           Property::Array* array = imageURLValue->GetArray();
           if( array )
           {
-            visualPtr = AnimatedImageVisual::New( GetFactoryCache(), *array, propertyMap );
+            visualPtr = AnimatedImageVisual::New( GetFactoryCache(), GetImageVisualShaderFactory(), *array, propertyMap );
           }
         }
       }
@@ -220,7 +222,7 @@ Toolkit::Visual::Base VisualFactory::CreateVisual( const Property::Map& property
       std::string imageUrl;
       if( imageURLValue && imageURLValue->Get( imageUrl ) )
       {
-        visualPtr = SvgVisual::New( GetFactoryCache(), imageUrl, propertyMap );
+        visualPtr = SvgVisual::New( GetFactoryCache(), GetImageVisualShaderFactory(), imageUrl, propertyMap );
       }
       break;
     }
@@ -233,14 +235,14 @@ Toolkit::Visual::Base VisualFactory::CreateVisual( const Property::Map& property
       {
         if( imageURLValue->Get( imageUrl ) )
         {
-          visualPtr = AnimatedImageVisual::New( GetFactoryCache(), imageUrl, propertyMap );
+          visualPtr = AnimatedImageVisual::New( GetFactoryCache(), GetImageVisualShaderFactory(), imageUrl, propertyMap );
         }
         else
         {
           Property::Array* array = imageURLValue->GetArray();
           if( array )
           {
-            visualPtr = AnimatedImageVisual::New( GetFactoryCache(), *array, propertyMap );
+            visualPtr = AnimatedImageVisual::New( GetFactoryCache(), GetImageVisualShaderFactory(), *array, propertyMap );
           }
         }
       }
@@ -281,7 +283,7 @@ Toolkit::Visual::Base VisualFactory::CreateVisual( const Image& image )
     }
     else
     {
-      visualPtr = ImageVisual::New(GetFactoryCache(), image );
+      visualPtr = ImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), image );
     }
   }
 
@@ -311,17 +313,17 @@ Toolkit::Visual::Base VisualFactory::CreateVisual( const std::string& url, Image
       }
       case VisualUrl::SVG:
       {
-        visualPtr = SvgVisual::New( GetFactoryCache(), visualUrl );
+        visualPtr = SvgVisual::New( GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl );
         break;
       }
       case VisualUrl::GIF:
       {
-        visualPtr = AnimatedImageVisual::New( GetFactoryCache(), visualUrl );
+        visualPtr = AnimatedImageVisual::New( GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl );
         break;
       }
       case VisualUrl::REGULAR_IMAGE:
       {
-        visualPtr = ImageVisual::New(GetFactoryCache(), visualUrl, size );
+        visualPtr = ImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl, size );
         break;
       }
     }
@@ -375,6 +377,15 @@ Internal::VisualFactoryCache& VisualFactory::GetFactoryCache()
   return *mFactoryCache;
 }
 
+ImageVisualShaderFactory& VisualFactory::GetImageVisualShaderFactory()
+{
+  if( !mImageVisualShaderFactory )
+  {
+    mImageVisualShaderFactory = std::unique_ptr< ImageVisualShaderFactory >( new ImageVisualShaderFactory() );
+  }
+  return *mImageVisualShaderFactory;
+}
+
 } // namespace Internal
 
 } // namespace Toolkit
index a9a6563..0e4dcb4 100644 (file)
@@ -37,6 +37,7 @@ namespace Internal
 {
 
 class VisualFactoryCache;
+class ImageVisualShaderFactory;
 
 /**
  * @copydoc Toolkit::VisualFactory
@@ -103,15 +104,21 @@ private:
    */
   Internal::VisualFactoryCache& GetFactoryCache();
 
+  /**
+   * Get the image visual shader factory, creating it if necessary.
+   */
+  ImageVisualShaderFactory& GetImageVisualShaderFactory();
+
   VisualFactory(const VisualFactory&) = delete;
 
   VisualFactory& operator=(const VisualFactory& rhs) = delete;
 
 private:
-  std::unique_ptr<VisualFactoryCache> mFactoryCache;
-  SlotDelegate< VisualFactory >       mSlotDelegate;
-  bool                                mDebugEnabled:1;
-  bool                                mPreMultiplyOnLoad:1; ///< Local store for this flag
+  std::unique_ptr< VisualFactoryCache >       mFactoryCache;
+  std::unique_ptr< ImageVisualShaderFactory > mImageVisualShaderFactory;
+  SlotDelegate< VisualFactory >               mSlotDelegate;
+  bool                                        mDebugEnabled:1;
+  bool                                        mPreMultiplyOnLoad:1; ///< Local store for this flag
 };
 
 /**