Tidied up ControlRenderer::DoInitialize methods.
Added ControlRerenderer::SetCachedRendererKey method to set a key and enable base ControlRenderer to cache core renderers from this key.
Added RendererFactoryCache::Get/Save/RemoveRenderer methods.
Change-Id: I48753b8fe18293ca53477e149f00018c50122bb0
* This function should be called when the control put on stage.
*
* @param[in] actor The actor applying this renderer.
+ * @post SetOffStage should be called with the same actor when the control is put off stage otherwise memory will be leaked
*/
void SetOnStage( Actor& actor );
);
}
-BorderRenderer::BorderRenderer()
-: ControlRenderer(),
+BorderRenderer::BorderRenderer( RendererFactoryCache& factoryCache )
+: ControlRenderer( factoryCache ),
mBorderColor( Color::TRANSPARENT ),
mBorderSize( 0.f ),
mBorderColorIndex( Property::INVALID_INDEX ),
{
}
-void BorderRenderer::DoInitialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap )
+void BorderRenderer::DoInitialize( const Property::Map& propertyMap )
{
- Initialize( factoryCache );
-
Property::Value* color = propertyMap.Find( COLOR_NAME );
if( !( color && color->Get(mBorderColor) ) )
{
map.Insert( SIZE_NAME, mBorderSize );
}
-void BorderRenderer::Initialize( RendererFactoryCache& factoryCache)
+void BorderRenderer::InitializeRenderer( Renderer& renderer )
{
- mImpl->mGeometry = factoryCache.GetGeometry( RendererFactoryCache::BORDER_GEOMETRY );
- if( !(mImpl->mGeometry) )
+ Geometry geometry = mFactoryCache.GetGeometry( RendererFactoryCache::BORDER_GEOMETRY );
+ if( !geometry )
+ {
+ geometry = CreateBorderGeometry();
+ mFactoryCache.SaveGeometry( RendererFactoryCache::QUAD_GEOMETRY, geometry );
+ }
+
+ Shader shader = mFactoryCache.GetShader( RendererFactoryCache::BORDER_SHADER );
+ if( !shader )
{
- mImpl->mGeometry = CreateBorderGeometry();
- factoryCache.SaveGeometry( RendererFactoryCache::QUAD_GEOMETRY, mImpl->mGeometry );
+ shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
+ mFactoryCache.SaveShader( RendererFactoryCache::COLOR_SHADER, shader );
}
- mImpl->mShader = factoryCache.GetShader( RendererFactoryCache::BORDER_SHADER );
- if( !(mImpl->mShader) )
+ if( !renderer )
{
- mImpl->mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
- factoryCache.SaveShader( RendererFactoryCache::COLOR_SHADER, mImpl->mShader );
+ Material material = Material::New( shader );
+ renderer = Renderer::New( geometry, material );
+ }
+ else
+ {
+ mImpl->mRenderer.SetGeometry( geometry );
+ Material material = mImpl->mRenderer.GetMaterial();
+ if( material )
+ {
+ material.SetShader( shader );
+ }
}
}
/**
* @brief Constructor.
+ *
+ * @param[in] factoryCache A pointer pointing to the RendererFactoryCache object
*/
- BorderRenderer();
+ BorderRenderer( RendererFactoryCache& factoryCache );
/**
* @brief A reference counted object may only be deleted by calling Unreference().
public: // from ControlRenderer
+ /**
+ * @copydoc ControlRenderer::SetClipRect
+ */
+ virtual void SetClipRect( const Rect<int>& clipRect );
+
+protected:
+
/**
* @copydoc ControlRenderer::DoInitialize
*/
- virtual void DoInitialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap );
+ virtual void DoInitialize( const Property::Map& propertyMap );
/**
- * @copydoc ControlRenderer::SetClipRect
+ * @copydoc ControlRenderer::InitializeRenderer
*/
- virtual void SetClipRect( const Rect<int>& clipRect );
+ virtual void InitializeRenderer( Renderer& renderer );
-protected:
/**
* @copydoc ControlRenderer::DoSetOnStage
*/
public:
- /**
- * Request the geometry and shader from the cache, if not available, create and save to the cache for sharing.
- *
- * @param[in] factoryCache A pointer pointing to the RendererFactoryCache object
- */
- void Initialize( RendererFactoryCache& factoryCache );
-
/**
* Set the color of the border.
* @param[in] color The border color.
);
}
-ColorRenderer::ColorRenderer()
-: ControlRenderer(),
+ColorRenderer::ColorRenderer( RendererFactoryCache& factoryCache )
+: ControlRenderer( factoryCache ),
mBlendColorIndex( Property::INVALID_INDEX )
{
}
{
}
-void ColorRenderer::DoInitialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap )
+void ColorRenderer::DoInitialize( const Property::Map& propertyMap )
{
- Initialize( factoryCache );
-
Property::Value* color = propertyMap.Find( COLOR_NAME );
if( !( color && color->Get(mBlendColor) ) )
{
map.Insert( COLOR_NAME, mBlendColor );
}
-void ColorRenderer::DoSetOnStage( Actor& actor )
+void ColorRenderer::InitializeRenderer( Renderer& renderer )
{
- mBlendColorIndex = (mImpl->mRenderer).RegisterProperty( COLOR_UNIFORM_NAME, mBlendColor );
- if( mBlendColor.a < 1.f )
+ Geometry geometry = mFactoryCache.GetGeometry( RendererFactoryCache::QUAD_GEOMETRY );
+ if( !geometry )
{
- (mImpl->mRenderer).GetMaterial().SetBlendMode( BlendingMode::ON );
+ geometry = RendererFactoryCache::CreateQuadGeometry();
+ mFactoryCache.SaveGeometry( RendererFactoryCache::QUAD_GEOMETRY, geometry );
}
-}
-void ColorRenderer::Initialize( RendererFactoryCache& factoryCache)
-{
- mImpl->mGeometry = factoryCache.GetGeometry( RendererFactoryCache::QUAD_GEOMETRY );
- if( !(mImpl->mGeometry) )
+ Shader shader = mFactoryCache.GetShader( RendererFactoryCache::COLOR_SHADER );
+ if( !shader )
+ {
+ shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
+ mFactoryCache.SaveShader( RendererFactoryCache::COLOR_SHADER, shader );
+ }
+
+ if( !renderer )
+ {
+ Material material = Material::New( shader );
+ renderer = Renderer::New( geometry, material );
+ }
+ else
{
- mImpl->mGeometry = RendererFactoryCache::CreateQuadGeometry();
- factoryCache.SaveGeometry( RendererFactoryCache::QUAD_GEOMETRY, mImpl->mGeometry );
+ mImpl->mRenderer.SetGeometry( geometry );
+ Material material = mImpl->mRenderer.GetMaterial();
+ if( material )
+ {
+ material.SetShader( shader );
+ }
}
- mImpl->mShader = factoryCache.GetShader( RendererFactoryCache::COLOR_SHADER );
- if( !(mImpl->mShader) )
+ mBlendColorIndex = renderer.RegisterProperty( COLOR_UNIFORM_NAME, mBlendColor );
+ if( mBlendColor.a < 1.f )
{
- mImpl->mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
- factoryCache.SaveShader( RendererFactoryCache::COLOR_SHADER, mImpl->mShader );
+ renderer.GetMaterial().SetBlendMode( BlendingMode::ON );
}
}
/**
* @brief Constructor.
+ *
+ * @param[in] factoryCache A pointer pointing to the RendererFactoryCache object
*/
- ColorRenderer();
+ ColorRenderer( RendererFactoryCache& factoryCache );
/**
* @brief A reference counted object may only be deleted by calling Unreference().
public: // from ControlRenderer
- /**
- * @copydoc ControlRenderer::DoInitialize
- */
- virtual void DoInitialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap );
-
/**
* @copydoc ControlRenderer::SetSize
*/
virtual void DoCreatePropertyMap( Property::Map& map ) const;
protected:
+
/**
- * @copydoc ControlRenderer::DoSetOnStage
+ * @copydoc ControlRenderer::DoInitialize
*/
- virtual void DoSetOnStage( Actor& actor );
-
-public:
+ virtual void DoInitialize( const Property::Map& propertyMap );
/**
- * Request the geometry and shader from the cache, if not available, create and save to the cache for sharing.
- *
- * @param[in] factoryCache A pointer pointing to the RendererFactoryCache object
+ * @copydoc ControlRenderer::InitializeRenderer
*/
- void Initialize( RendererFactoryCache& factoryCache );
+ virtual void InitializeRenderer( Renderer& renderer );
+
+public:
/**
* Set the color for rendering.
void CreatePropertyMap( Property::Map& map ) const;
};
- Geometry mGeometry;
- Shader mShader;
+ std::string mCachedRendererKey; ///< The key to use for caching of the renderer. If it is empty then no caching will occur
+ RendererFactoryCache::CachedRendererPtr mCachedRenderer; ///< The current cached renderer from the Factory Cache. mCachedRenderer == null whilst this control render is offstage
Renderer mRenderer;
CustomShader* mCustomShader;
namespace Internal
{
-ControlRenderer::ControlRenderer()
-: mImpl( new Impl() )
+ControlRenderer::ControlRenderer( RendererFactoryCache& factoryCache )
+: mImpl( new Impl() ),
+ mFactoryCache( factoryCache )
{
}
delete mImpl;
}
-void ControlRenderer::Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap )
+void ControlRenderer::Initialize( const Property::Map& propertyMap )
{
if( mImpl->mCustomShader )
{
}
}
}
- DoInitialize( factoryCache, propertyMap );
+ DoInitialize( propertyMap );
+
+ if( mImpl->mIsOnStage )
+ {
+ InitializeRenderer( mImpl->mRenderer );
+ }
}
void ControlRenderer::SetSize( const Vector2& size )
return mImpl->mDepthIndex;
}
+void ControlRenderer::SetCachedRendererKey( const std::string& cachedRendererKey )
+{
+ if( mImpl->mCachedRendererKey == cachedRendererKey )
+ {
+ return;
+ }
+ if( !mImpl->mIsOnStage )
+ {
+ mImpl->mCachedRendererKey = cachedRendererKey;
+ }
+ else
+ {
+ //remove the cached renderer from the cache if we and the cache are the only things that hold a reference to it
+ if( mImpl->mCachedRenderer && mImpl->mCachedRenderer->ReferenceCount() == 2 )
+ {
+ mFactoryCache.RemoveRenderer( mImpl->mCachedRenderer->mKey );
+ }
+ mImpl->mCachedRenderer.Reset();
+
+ //add the new renderer
+ mImpl->mCachedRendererKey = cachedRendererKey;
+ if( !mImpl->mCachedRendererKey.empty() && !mImpl->mCustomShader )
+ {
+ DALI_ASSERT_DEBUG( mImpl->mRenderer && "The control render is on stage but it doesn't have a valid renderer.");
+ mImpl->mCachedRenderer = mFactoryCache.SaveRenderer( mImpl->mCachedRendererKey, mImpl->mRenderer );
+ }
+ }
+}
+
void ControlRenderer::SetOnStage( Actor& actor )
{
- Material material = Material::New( mImpl->mShader );
- mImpl->mRenderer = Renderer::New( mImpl->mGeometry, material );
+ if( !mImpl->mCachedRendererKey.empty() && !mImpl->mCustomShader )
+ {
+ mImpl->mCachedRenderer = mFactoryCache.GetRenderer( mImpl->mCachedRendererKey );
+ if( !mImpl->mCachedRenderer || !mImpl->mCachedRenderer->mRenderer )
+ {
+ InitializeRenderer( mImpl->mRenderer );
+ mImpl->mCachedRenderer = mFactoryCache.SaveRenderer( mImpl->mCachedRendererKey, mImpl->mRenderer );
+ }
+
+ if( mImpl->mCachedRenderer && mImpl->mCachedRenderer->mRenderer )
+ {
+ mImpl->mRenderer = mImpl->mCachedRenderer->mRenderer;
+ }
+ }
+
+ if( !mImpl->mRenderer )
+ {
+ InitializeRenderer( mImpl->mRenderer );
+ }
+
mImpl->mRenderer.SetDepthIndex( mImpl->mDepthIndex );
actor.AddRenderer( mImpl->mRenderer );
mImpl->mIsOnStage = true;
{
DoSetOffStage( actor );
+ //remove the cached renderer from the cache if we and the cache are the only things that hold a reference to it
+ if( mImpl->mCachedRenderer && mImpl->mCachedRenderer->ReferenceCount() == 2 )
+ {
+ mFactoryCache.RemoveRenderer( mImpl->mCachedRenderer->mKey );
+ }
+ mImpl->mCachedRenderer.Reset();
+
actor.RemoveRenderer( mImpl->mRenderer );
mImpl->mRenderer.Reset();
// INTERNAL INCLUDES
#include <dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.h>
#include <dali-toolkit/devel-api/controls/renderer-factory/control-renderer.h>
+#include <dali-toolkit/internal/controls/renderers/renderer-factory-cache.h>
namespace Dali
{
namespace Internal
{
-class RendererFactoryCache;
-
/**
* Base class for all Control rendering logic. A control may have multiple control renderers.
*
* request the geometry and shader from the cache, if not available, create and save to the cache for sharing;
* record the property values.
*
- * @param[in] factoryCache A pointer pointing to the RendererFactoryCache object
* @param[in] propertyMap The properties for the requested ControlRenderer object.
*/
- void Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap );
+ void Initialize( const Property::Map& propertyMap );
/**
* @copydoc Toolkit::ControlRenderer::SetSize
/**
* @brief Constructor.
+ *
+ * @param[in] factoryCache A pointer pointing to the RendererFactoryCache object
*/
- ControlRenderer();
+ ControlRenderer( RendererFactoryCache& factoryCache );
/**
* @brief A reference counted object may only be deleted by calling Unreference().
* @param[in] factoryCache A pointer pointing to the RendererFactoryCache object
* @param[in] propertyMap The properties for the requested ControlRenderer object.
*/
- virtual void DoInitialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap ) = 0;
+ virtual void DoInitialize( const Property::Map& propertyMap ) = 0;
+
+ /**
+ * @brief Initialises a renderer ready to be put on stage.
+ *
+ * @param[inout] renderer The Renderer to initialise. If the renderer is not empty then re-initialise the renderer
+ */
+ virtual void InitializeRenderer( Renderer& renderer ) = 0;
protected:
*/
virtual void DoSetOffStage( Actor& actor );
+protected:
+
+ /**
+ * @brief Sets the key to use for caching the renderer. If this is empty then no caching will occur
+ *
+ * @param[in] cachedRendererKey The key to use for caching the renderer.
+ */
+ void SetCachedRendererKey( const std::string& cachedRendererKey );
+
private:
// Undefined
protected:
struct Impl;
Impl* mImpl;
+ RendererFactoryCache& mFactoryCache;
};
} // namespace Internal
}
-GradientRenderer::GradientRenderer()
-:mGradientTransformIndex( Property::INVALID_INDEX )
+GradientRenderer::GradientRenderer( RendererFactoryCache& factoryCache )
+: ControlRenderer( factoryCache ),
+ mGradientType( LINEAR )
{
}
{
}
-void GradientRenderer::DoInitialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap )
+void GradientRenderer::DoInitialize( const Property::Map& propertyMap )
{
- mImpl->mGeometry = factoryCache.GetGeometry( RendererFactoryCache::QUAD_GEOMETRY );
- if( !(mImpl->mGeometry) )
- {
- mImpl->mGeometry = RendererFactoryCache::CreateQuadGeometry();
- factoryCache.SaveGeometry( RendererFactoryCache::QUAD_GEOMETRY, mImpl->mGeometry );
- }
-
Gradient::GradientUnits gradientUnits = Gradient::OBJECT_BOUNDING_BOX;
Property::Value* unitsValue = propertyMap.Find( GRADIENT_UNITS_NAME );
std::string units;
gradientUnits = Gradient::USER_SPACE_ON_USE;
}
- Type gradientType = LINEAR;
+ mGradientType = LINEAR;
if( propertyMap.Find( GRADIENT_RADIUS_NAME ))
{
- gradientType = RADIAL;
- }
-
- RendererFactoryCache::ShaderType shaderType = GetShaderType( gradientType, gradientUnits );
-
- mImpl->mShader = factoryCache.GetShader( shaderType );
- if( !(mImpl->mShader) )
- {
- mImpl->mShader = Shader::New( VERTEX_SHADER[gradientUnits], FRAGMENT_SHADER[gradientType] );
- factoryCache.SaveShader( shaderType, mImpl->mShader );
+ mGradientType = RADIAL;
}
- if( NewGradient(gradientType, propertyMap) )
+ if( NewGradient( mGradientType, propertyMap ) )
{
mGradient->SetGradientUnits( gradientUnits );
mGradientTransform = mGradient->GetAlignmentTransform();
}
}
-void GradientRenderer::DoSetOnStage( Actor& actor )
+void GradientRenderer::InitializeRenderer( Dali::Renderer& renderer )
{
- mGradientTransformIndex = (mImpl->mRenderer).RegisterProperty( UNIFORM_ALIGNMENT_MATRIX_NAME, mGradientTransform );
+ Geometry geometry = mFactoryCache.GetGeometry( RendererFactoryCache::QUAD_GEOMETRY );
+ if( !geometry )
+ {
+ geometry = RendererFactoryCache::CreateQuadGeometry();
+ mFactoryCache.SaveGeometry( RendererFactoryCache::QUAD_GEOMETRY, geometry );
+ }
+
+ Gradient::GradientUnits gradientUnits = mGradient->GetGradientUnits();
+ RendererFactoryCache::ShaderType shaderType = GetShaderType( mGradientType, gradientUnits );
+ Shader shader = mFactoryCache.GetShader( shaderType );
+ if( !shader )
+ {
+ shader = Shader::New( VERTEX_SHADER[gradientUnits], FRAGMENT_SHADER[ mGradientType ] );
+ mFactoryCache.SaveShader( shaderType, shader );
+ }
+
+ Material material;
+ if( !renderer )
+ {
+ material = Material::New( shader );
+ renderer = Renderer::New( geometry, material );
+ }
+ else
+ {
+ mImpl->mRenderer.SetGeometry( geometry );
+ material = mImpl->mRenderer.GetMaterial();
+ if( material )
+ {
+ material.SetShader( shader );
+ }
+ }
Dali::BufferImage lookupTexture = mGradient->GenerateLookupTexture();
Sampler sampler = Sampler::New( lookupTexture, UNIFORM_TEXTULRE_NAME );
Sampler::WrapMode wrap = GetWrapMode( mGradient->GetSpreadMethod() );
sampler.SetWrapMode( wrap, wrap );
- Material material = (mImpl->mRenderer).GetMaterial();
- if( material )
- {
- material.AddSampler( sampler );
- }
+ material.AddSampler( sampler );
+
+ renderer.RegisterProperty( UNIFORM_ALIGNMENT_MATRIX_NAME, mGradientTransform );
}
bool GradientRenderer::NewGradient(Type gradientType, const Property::Map& propertyMap)
/**
* @brief Constructor.
+ *
+ * @param[in] factoryCache A pointer pointing to the RendererFactoryCache object
*/
- GradientRenderer();
+ GradientRenderer( RendererFactoryCache& factoryCache );
/**
* @brief A reference counted object may only be deleted by calling Unreference().
public: // from ControlRenderer
- /**
- * @copydoc ControlRenderer::DoInitialize
- */
- virtual void DoInitialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap );
-
/**
* @copydoc ControlRenderer::SetSize
*/
protected:
/**
- * @copydoc ControlRenderer::DoSetOnStage
+ * @copydoc ControlRenderer::DoInitialize
+ */
+ virtual void DoInitialize( const Property::Map& propertyMap );
+
+ /**
+ * @copydoc ControlRenderer::InitializeRenderer
*/
- virtual void DoSetOnStage( Actor& actor );
+ virtual void InitializeRenderer( Renderer& renderer );
private:
private:
Matrix3 mGradientTransform;
- Property::Index mGradientTransformIndex;
IntrusivePtr<Gradient> mGradient;
+ Type mGradientType;
};
} // namespace Internal
} //unnamed namespace
-ImageRenderer::ImageRenderer()
-: ControlRenderer(),
+ImageRenderer::ImageRenderer( RendererFactoryCache& factoryCache )
+: ControlRenderer( factoryCache ),
mDesiredSize(),
mFittingMode( FittingMode::DEFAULT ),
mSamplingMode( SamplingMode::DEFAULT )
{
}
-void ImageRenderer::DoInitialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap )
+void ImageRenderer::DoInitialize( const Property::Map& propertyMap )
{
- Initialize(factoryCache);
-
Property::Value* imageURLValue = propertyMap.Find( IMAGE_URL_NAME );
if( imageURLValue )
{
imageURLValue->Get( mImageUrl );
if( !mImageUrl.empty() )
{
+ SetCachedRendererKey( mImageUrl );
mImage.Reset();
}
{
}
+void ImageRenderer::InitializeRenderer( Renderer& renderer )
+{
+ Geometry geometry;
+ Shader shader;
+ if( !mImpl->mCustomShader )
+ {
+ geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) );
+
+ shader = mFactoryCache.GetShader( RendererFactoryCache::IMAGE_SHADER );
+ if( !shader )
+ {
+ shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
+ mFactoryCache.SaveShader( RendererFactoryCache::IMAGE_SHADER, shader );
+ }
+ }
+ else
+ {
+ geometry = CreateGeometry( mFactoryCache, mImpl->mCustomShader->mGridSize );
+
+ if( mImpl->mCustomShader->mVertexShader.empty() && mImpl->mCustomShader->mFragmentShader.empty() )
+ {
+ shader = mFactoryCache.GetShader( RendererFactoryCache::IMAGE_SHADER );
+ if( !shader )
+ {
+ shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
+ mFactoryCache.SaveShader( RendererFactoryCache::IMAGE_SHADER, shader );
+ }
+ }
+ else
+ {
+ shader = Shader::New( mImpl->mCustomShader->mVertexShader.empty() ? VERTEX_SHADER : mImpl->mCustomShader->mVertexShader,
+ mImpl->mCustomShader->mFragmentShader.empty() ? FRAGMENT_SHADER : mImpl->mCustomShader->mFragmentShader,
+ mImpl->mCustomShader->mHints );
+ }
+ }
+
+ if( !renderer )
+ {
+ Material material = Material::New( shader );
+ renderer = Renderer::New( geometry, material );
+ }
+ else
+ {
+ renderer.SetGeometry( geometry );
+ Material material = renderer.GetMaterial();
+ if( material )
+ {
+ material.SetShader( shader );
+ }
+ }
+}
+
void ImageRenderer::DoSetOnStage( Actor& actor )
{
if( !mImageUrl.empty() && !mImage )
}
}
-void ImageRenderer::Initialize( RendererFactoryCache& factoryCache )
-{
- if( !mImpl->mCustomShader )
- {
- mImpl->mGeometry = CreateGeometry( factoryCache, ImageDimensions( 1, 1 ) );
-
- mImpl->mShader = factoryCache.GetShader( RendererFactoryCache::IMAGE_SHADER );
-
- if( !mImpl->mShader )
- {
- mImpl->mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
- factoryCache.SaveShader( RendererFactoryCache::IMAGE_SHADER, mImpl->mShader );
- }
- }
- else
- {
- mImpl->mGeometry = CreateGeometry( factoryCache, mImpl->mCustomShader->mGridSize );
-
- if( mImpl->mCustomShader->mVertexShader.empty() && mImpl->mCustomShader->mFragmentShader.empty() )
- {
- mImpl->mShader = factoryCache.GetShader( RendererFactoryCache::IMAGE_SHADER );
-
- if( !mImpl->mShader )
- {
- mImpl->mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
- factoryCache.SaveShader( RendererFactoryCache::IMAGE_SHADER, mImpl->mShader );
- }
- }
- else
- {
- mImpl->mShader = Shader::New( mImpl->mCustomShader->mVertexShader.empty() ? VERTEX_SHADER : mImpl->mCustomShader->mVertexShader,
- mImpl->mCustomShader->mFragmentShader.empty() ? FRAGMENT_SHADER : mImpl->mCustomShader->mFragmentShader,
- mImpl->mCustomShader->mHints );
- }
- }
-
- if( mImpl->mRenderer )
- {
- mImpl->mRenderer.SetGeometry( mImpl->mGeometry );
- Material material = mImpl->mRenderer.GetMaterial();
- if( material )
- {
- material.SetShader( mImpl->mShader );
- }
- }
-}
-
void ImageRenderer::SetImage( const std::string& imageUrl )
{
SetImage( imageUrl, 0, 0, Dali::FittingMode::DEFAULT, Dali::SamplingMode::DEFAULT );
if( mImageUrl != imageUrl )
{
mImageUrl = imageUrl;
+ SetCachedRendererKey( mImageUrl );
mDesiredSize = ImageDimensions( desiredWidth, desiredHeight );
mFittingMode = fittingMode;
mSamplingMode = samplingMode;
/**
* @brief Constructor.
+ *
+ * @param[in] factoryCache A pointer pointing to the RendererFactoryCache object
*/
- ImageRenderer();
+ ImageRenderer( RendererFactoryCache& factoryCache );
/**
* @brief A reference counted object may only be deleted by calling Unreference().
public: // from ControlRenderer
- /**
- * @copydoc ControlRenderer::DoInitialize
- */
- virtual void DoInitialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap );
-
/**
* @copydoc ControlRenderer::SetSize
*/
virtual void DoCreatePropertyMap( Property::Map& map ) const;
protected:
+ /**
+ * @copydoc ControlRenderer::DoInitialize
+ */
+ virtual void DoInitialize( const Property::Map& propertyMap );
+
/**
* @copydoc ControlRenderer::DoSetOnStage
*/
*/
virtual void DoSetOffStage( Actor& actor );
-public:
-
/**
- * Request the geometry and shader from the cache, if not available, create and save to the cache for sharing.
- *
- * @param[in] factoryCache A pointer pointing to the RendererFactoryCache object
+ * @copydoc ControlRenderer::InitializeRenderer
*/
- void Initialize( RendererFactoryCache& factoryCache );
+ virtual void InitializeRenderer( Renderer& renderer );
+
+public:
/**
* @brief Sets the image of this renderer to the resource at imageUrl
/////////////////NPatchRenderer////////////////
-NPatchRenderer::NPatchRenderer()
-: ControlRenderer(),
+NPatchRenderer::NPatchRenderer( RendererFactoryCache& factoryCache )
+: ControlRenderer( factoryCache ),
mBorderOnly( false )
{
}
{
}
-void NPatchRenderer::DoInitialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap )
+void NPatchRenderer::DoInitialize( const Property::Map& propertyMap )
{
- Initialize(factoryCache);
-
Property::Value* imageURLValue = propertyMap.Find( IMAGE_URL_NAME );
if( imageURLValue )
{
//ToDo: renderer applies the offset
}
+void NPatchRenderer::InitializeRenderer( Renderer& renderer )
+{
+ Geometry geometry;
+ if( !mBorderOnly )
+ {
+ geometry = mFactoryCache.GetGeometry( RendererFactoryCache::NINE_PATCH_GEOMETRY );
+ if( !geometry )
+ {
+ geometry = CreateGeometry( Uint16Pair( 3, 3 ) );
+ mFactoryCache.SaveGeometry( RendererFactoryCache::NINE_PATCH_GEOMETRY, geometry );
+ }
+ }
+ else
+ {
+ geometry = mFactoryCache.GetGeometry( RendererFactoryCache::NINE_PATCH_BORDER_GEOMETRY );
+ if( !geometry )
+ {
+ geometry = CreateGeometryBorder( Uint16Pair( 3, 3 ) );
+ mFactoryCache.SaveGeometry( RendererFactoryCache::NINE_PATCH_BORDER_GEOMETRY, geometry );
+ }
+ }
+
+ Shader shader = mFactoryCache.GetShader( RendererFactoryCache::NINE_PATCH_SHADER );
+ if( !shader )
+ {
+ shader = Shader::New( VERTEX_SHADER_3X3, FRAGMENT_SHADER );
+ mFactoryCache.SaveShader( RendererFactoryCache::NINE_PATCH_SHADER, shader );
+ }
+
+ if( !renderer )
+ {
+ Material material = Material::New( shader );
+ renderer = Renderer::New( geometry, material );
+ }
+ else
+ {
+ mImpl->mRenderer.SetGeometry( geometry );
+ Material material = mImpl->mRenderer.GetMaterial();
+ if( material )
+ {
+ material.SetShader( shader );
+ }
+ }
+}
+
void NPatchRenderer::DoSetOnStage( Actor& actor )
{
if( !mCroppedImage )
map.Insert( BORDER_ONLY, mBorderOnly );
}
-void NPatchRenderer::Initialize( RendererFactoryCache& factoryCache )
-{
- mNinePatchGeometry = factoryCache.GetGeometry( RendererFactoryCache::NINE_PATCH_GEOMETRY );
- if( !(mNinePatchGeometry) )
- {
- mNinePatchGeometry = CreateGeometry( Uint16Pair( 3, 3 ) );
- factoryCache.SaveGeometry( RendererFactoryCache::NINE_PATCH_GEOMETRY, mNinePatchGeometry );
- }
-
- mNinePatchBorderGeometry = factoryCache.GetGeometry( RendererFactoryCache::NINE_PATCH_BORDER_GEOMETRY );
- if( !(mNinePatchBorderGeometry) )
- {
- mNinePatchBorderGeometry = CreateGeometryBorder( Uint16Pair( 3, 3 ) );
- factoryCache.SaveGeometry( RendererFactoryCache::NINE_PATCH_BORDER_GEOMETRY, mNinePatchBorderGeometry );
- }
-
- mNinePatchShader = factoryCache.GetShader( RendererFactoryCache::NINE_PATCH_SHADER );
- if( !mNinePatchShader )
- {
- mNinePatchShader = Shader::New( VERTEX_SHADER_3X3, FRAGMENT_SHADER );
- factoryCache.SaveShader( RendererFactoryCache::NINE_PATCH_SHADER, mNinePatchShader );
- }
-
- mImpl->mGeometry = mNinePatchGeometry;
- mImpl->mShader = mNinePatchShader;
-
- mImageUrl.clear();
-}
-
void NPatchRenderer::SetImage( const std::string& imageUrl, bool borderOnly )
{
mBorderOnly = borderOnly;
mStretchPixelsX = nPatch.GetStretchPixelsX();
mStretchPixelsY = nPatch.GetStretchPixelsY();
-
- if( mStretchPixelsX.Size() > 0 && mStretchPixelsY.Size() > 0 )
- {
- //only 9 patch supported for now
- mImpl->mGeometry = !mBorderOnly ? mNinePatchGeometry : mNinePatchBorderGeometry;
- mImpl->mShader = mNinePatchShader;
- }
}
void NPatchRenderer::CreateErrorImage()
mStretchPixelsX.PushBack( Uint16Pair( 0, mImageSize.GetWidth() ) );
mStretchPixelsY.Clear();
mStretchPixelsY.PushBack( Uint16Pair( 0, mImageSize.GetHeight() ) );
-
- mImpl->mGeometry = mNinePatchGeometry;
- mImpl->mShader = mNinePatchShader;
}
void NPatchRenderer::ApplyImageToSampler()
/**
* @brief Constructor.
+ *
+ * @param[in] factoryCache A pointer pointing to the RendererFactoryCache object
*/
- NPatchRenderer();
+ NPatchRenderer( RendererFactoryCache& factoryCache );
/**
* @brief A reference counted object may only be deleted by calling Unreference().
public: // from ControlRenderer
- /**
- * @copydoc ControlRenderer::DoInitialize
- */
- virtual void DoInitialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap );
-
/**
* @copydoc ControlRenderer::GetNaturalSize
*/
virtual void DoCreatePropertyMap( Property::Map& map ) const;
protected:
+
+ /**
+ * @copydoc ControlRenderer::DoInitialize
+ */
+ virtual void DoInitialize( const Property::Map& propertyMap );
+
+ /**
+ * @copydoc ControlRenderer::InitializeRenderer
+ */
+ virtual void InitializeRenderer( Renderer& renderer );
+
/**
* @copydoc ControlRenderer::DoSetOnStage
*/
public:
- /**
- * Request the geometry and shader from the cache, if not available, create and save to the cache for sharing.
- *
- * @param[in] factoryCache A pointer pointing to the RendererFactoryCache object
- */
- void Initialize( RendererFactoryCache& factoryCache );
-
/**
* @brief Sets the 9 patch image of this renderer to the resource at imageUrl
* The renderer will load the image synchronously when the associated actor is put on stage, and destroy the image when it is off stage
Image mCroppedImage;
Geometry mNinePatchGeometry;
Geometry mNinePatchBorderGeometry;
- Shader mNinePatchShader;
std::string mImageUrl; ///< The url to the image resource to render if the renderer was set from an image resource url, empty otherwise
NinePatchImage::StretchRanges mStretchPixelsX;
// CLASS HEADER
#include "renderer-factory-cache.h"
-// Internal HEADER
+// EXTERNAL HEADER
+#include <dali/devel-api/common/hash.h>
+
+// INTERNAL HEADER
#include <dali-toolkit/internal/controls/renderers/color/color-renderer.h>
namespace Dali
RendererFactoryCache::~RendererFactoryCache()
{
- for( int i=0; i<= SHADER_TYPE_MAX; i++)
- {
- if(mShader[i])
- {
- mShader[i].Reset();
- }
- }
-
- for( int i=0; i<= GEOMETRY_TYPE_MAX; i++)
- {
- if(mGeometry[i])
- {
- mGeometry[i].Reset();
- }
- }
}
-
Geometry RendererFactoryCache::GetGeometry( GeometryType type )
{
return mGeometry[type];
mShader[type] = shader;
}
+int RendererFactoryCache::FindRenderer( const std::string& key ) const
+{
+ int hash = Dali::CalculateHash( key );
+
+ HashVector::Iterator startIt = mRendererHashes.Begin();
+ HashVector::Iterator it;
+
+ for(;;)
+ {
+ it = std::find( startIt, mRendererHashes.End(), hash );
+ if( it != mRendererHashes.End() )
+ {
+ int index = it - mRendererHashes.Begin();
+ const CachedRendererPtr& cachedRenderer = mRenderers[ index ];
+
+ if( cachedRenderer && cachedRenderer->mKey == key )
+ {
+ return index;
+ }
+ }
+ else
+ {
+ break;
+ }
+ startIt = it + 1;
+ }
+
+ return -1;
+}
+
+RendererFactoryCache::CachedRendererPtr RendererFactoryCache::GetRenderer( const std::string& key ) const
+{
+ int index = FindRenderer( key );
+ if( index != -1 )
+ {
+ return mRenderers[ index ];
+ }
+ else
+ {
+ return CachedRendererPtr();
+ }
+}
+
+RendererFactoryCache::CachedRendererPtr RendererFactoryCache::SaveRenderer( const std::string& key, Renderer& renderer )
+{
+ int hash = Dali::CalculateHash( key );
+ CachedRendererPtr newCachedRenderer = new CachedRenderer( key, renderer );
+
+ CachedRenderers::iterator it = std::find(mRenderers.begin(), mRenderers.end(), CachedRendererPtr() );
+ if( it != mRenderers.end() )
+ {
+ *it = newCachedRenderer;
+ int index = it - mRenderers.begin();
+ mRendererHashes[ index ] = hash;
+ }
+ else
+ {
+ mRendererHashes.PushBack( hash );
+ mRenderers.push_back( newCachedRenderer );
+ }
+
+ return newCachedRenderer;
+}
+
+void RendererFactoryCache::RemoveRenderer( const std::string& key )
+{
+ int index = FindRenderer( key );
+ if( index != -1 )
+ {
+ mRendererHashes[ index ] = Dali::CalculateHash( "" );
+ mRenderers[ index ].Reset();
+ }
+}
+
Geometry RendererFactoryCache::CreateQuadGeometry()
{
const float halfWidth = 0.5f;
* limitations under the License.
*/
+#include <map>
+
// EXTERNAL INCLUDES
#include <dali/public-api/object/ref-object.h>
#include <dali/devel-api/rendering/geometry.h>
#include <dali/devel-api/rendering/shader.h>
+#include <dali/devel-api/rendering/renderer.h>
namespace Dali
{
*/
static Geometry CreateQuadGeometry();
+public:
+ struct CachedRenderer : RefObject
+ {
+ std::string mKey;
+ Renderer mRenderer;
+
+ CachedRenderer( const std::string& key, const Renderer& renderer )
+ : mKey( key ),
+ mRenderer( renderer )
+ {}
+ };
+
+ typedef IntrusivePtr< CachedRenderer > CachedRendererPtr;
+
+ /**
+ * @brief Request renderer from the url
+ *
+ * @return The cached renderer if exist in the cache. Otherwise null is returned.
+ */
+ CachedRendererPtr GetRenderer( const std::string& key ) const;
+
+ /**
+ * @brief Cache the renderer based on the given key.
+ *
+ * If the key already exists in the cache, then the cache will save an additional renderer to the cache.
+ * RemoveRenderer will then need to be called twice to remove both items from the cache.
+ *
+ * @param[in] key The key to use for caching
+ * @param[in] renderer The Renderer to be cached
+ *
+ * @return The cached renderer stored in the cache
+ */
+ CachedRendererPtr SaveRenderer( const std::string& key, Renderer& renderer );
+
+ /**
+ * @brief Removes the renderer from the cache based on the given key
+ *
+ * @param[in] key The key used for caching
+ */
+ void RemoveRenderer( const std::string& key );
+
protected:
/**
RendererFactoryCache& operator=(const RendererFactoryCache& rhs);
private:
+ typedef Dali::Vector< std::size_t > HashVector;
+ typedef std::vector< CachedRendererPtr > CachedRenderers;
+ /**
+ * @brief Finds the first index into the cached renderers from the url
+ *
+ * @return Returns the first index into the cached renderer from the url if it exists in the cache, otherwise returns -1
+ */
+ int FindRenderer( const std::string& key ) const;
+
+private:
// ToDo: test whether using the WeakHandle could improve the performance
// With WeakHandle, the resource would be released automatically when no control is using it
Geometry mGeometry[GEOMETRY_TYPE_MAX+1];
Shader mShader[SHADER_TYPE_MAX+1];
+
+ HashVector mRendererHashes;
+ CachedRenderers mRenderers;
};
} // namespace Internal
std::string typeValue ;
if( type && type->Get( typeValue ))
{
+ if( !mFactoryCache )
+ {
+ mFactoryCache = new RendererFactoryCache();
+ }
+
if( typeValue == COLOR_RENDERER )
{
- rendererPtr = new ColorRenderer();
+ rendererPtr = new ColorRenderer( *( mFactoryCache.Get() ) );
}
else if( typeValue == GRADIENT_RENDERER )
{
- rendererPtr = new GradientRenderer();
+ rendererPtr = new GradientRenderer( *( mFactoryCache.Get() ) );
}
else if( typeValue == IMAGE_RENDERER )
{
- rendererPtr = new ImageRenderer();
+ rendererPtr = new ImageRenderer( *( mFactoryCache.Get() ) );
}
else if( typeValue == N_PATCH_RENDERER )
{
- rendererPtr = new NPatchRenderer();
+ rendererPtr = new NPatchRenderer( *( mFactoryCache.Get() ) );
}
else if( typeValue == BORDER_RENDERER )
{
- rendererPtr = new BorderRenderer();
+ rendererPtr = new BorderRenderer( *( mFactoryCache.Get() ) );
}
}
if( rendererPtr )
{
- if( !mFactoryCache )
- {
- mFactoryCache = new RendererFactoryCache();
- }
- rendererPtr->Initialize( *( mFactoryCache.Get() ), propertyMap );
+ rendererPtr->Initialize( propertyMap );
}
else
{
Toolkit::ControlRenderer RendererFactory::GetControlRenderer( const Vector4& color )
{
- ColorRenderer* rendererPtr = new ColorRenderer();
-
if( !mFactoryCache )
{
mFactoryCache = new RendererFactoryCache();
}
- rendererPtr->Initialize( *( mFactoryCache.Get() ) );
+ ColorRenderer* rendererPtr = new ColorRenderer( *( mFactoryCache.Get() ) );
rendererPtr->SetColor( color );
return Toolkit::ControlRenderer( rendererPtr );
Toolkit::ControlRenderer RendererFactory::GetControlRenderer( float borderSize, const Vector4& borderColor )
{
- BorderRenderer* rendererPtr = new BorderRenderer();
+ if( !mFactoryCache )
+ {
+ mFactoryCache = new RendererFactoryCache();
+ }
+ BorderRenderer* rendererPtr = new BorderRenderer( *mFactoryCache.Get() );
if( !mFactoryCache )
{
mFactoryCache = new RendererFactoryCache();
}
- rendererPtr->Initialize( *( mFactoryCache.Get() ) );
rendererPtr->SetBorderSize( borderSize );
rendererPtr->SetBorderColor( borderColor );
NinePatchImage npatchImage = NinePatchImage::DownCast( image );
if( npatchImage )
{
- NPatchRenderer* rendererPtr = new NPatchRenderer();
- rendererPtr->Initialize( *( mFactoryCache.Get() ) );
+ NPatchRenderer* rendererPtr = new NPatchRenderer( *( mFactoryCache.Get() ) );
rendererPtr->SetImage( npatchImage );
return Toolkit::ControlRenderer( rendererPtr );
}
else
{
- ImageRenderer* rendererPtr = new ImageRenderer();
- rendererPtr->Initialize( *( mFactoryCache.Get() ) );
+ ImageRenderer* rendererPtr = new ImageRenderer( *( mFactoryCache.Get() ) );
rendererPtr->SetImage( image );
return Toolkit::ControlRenderer( rendererPtr );
Toolkit::ControlRenderer RendererFactory::GetControlRenderer( const std::string& url )
{
+ if( !mFactoryCache )
+ {
+ mFactoryCache = new RendererFactoryCache();
+ }
+
if( NinePatchImage::IsNinePatchUrl( url ) )
{
- NPatchRenderer* rendererPtr = new NPatchRenderer();
- if( !mFactoryCache )
- {
- mFactoryCache = new RendererFactoryCache();
- }
- rendererPtr->Initialize( *( mFactoryCache.Get() ) );
+ NPatchRenderer* rendererPtr = new NPatchRenderer( *( mFactoryCache.Get() ) );
rendererPtr->SetImage( url );
return Toolkit::ControlRenderer( rendererPtr );
}
else
{
- ImageRenderer* rendererPtr = new ImageRenderer();
- if( !mFactoryCache )
- {
- mFactoryCache = new RendererFactoryCache();
- }
- rendererPtr->Initialize( *( mFactoryCache.Get() ) );
+ ImageRenderer* rendererPtr = new ImageRenderer( *( mFactoryCache.Get() ) );
rendererPtr->SetImage( url );
return Toolkit::ControlRenderer( rendererPtr );
}
}
- if( !mFactoryCache )
- {
- mFactoryCache = new RendererFactoryCache();
- }
- GetImplementation( renderer ).Initialize( *( mFactoryCache.Get() ), propertyMap );
+ GetImplementation( renderer ).Initialize( propertyMap );
return false;
}