From: Chu Hoang Date: Thu, 15 Oct 2015 10:48:26 +0000 (+0100) Subject: Refactored ControlRenderer so that derived classes are responsible for the creation... X-Git-Tag: dali_1.1.8~2^2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=8991dd870badfb20693aa0eb1acf0aedbe88f99f Refactored ControlRenderer so that derived classes are responsible for the creation of the renderer. This allows ImageRenderer to fully manage the life cycle of the renderer, fixing the bug where changing an image in an ImageView whilsts it is on the stage also changes the cached renderer and therefore any other actor that used that cached renderer. Change-Id: I2e8ba678445751c95c961f43da5be9a3f3cf1c58 --- diff --git a/automated-tests/src/dali-toolkit/utc-Dali-ControlRenderer.cpp b/automated-tests/src/dali-toolkit/utc-Dali-ControlRenderer.cpp index e0b50d1..84df350 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-ControlRenderer.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-ControlRenderer.cpp @@ -262,7 +262,8 @@ int UtcDaliControlRendererGetPropertyMap1(void) DALI_TEST_CHECK( colorValue->Get() == Color::BLUE ); // change the blend color - factory.ResetRenderer( colorRenderer, Color::CYAN ); + Actor actor; + factory.ResetRenderer( colorRenderer, actor, Color::CYAN ); colorRenderer.CreatePropertyMap( resultMap ); colorValue = resultMap.Find( "blend-color", Property::VECTOR4 ); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-RendererFactory.cpp b/automated-tests/src/dali-toolkit/utc-Dali-RendererFactory.cpp index 3b603b0..a3d65a7 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-RendererFactory.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-RendererFactory.cpp @@ -788,16 +788,14 @@ int UtcDaliRendererFactoryResetRenderer1(void) DALI_TEST_CHECK( gl.GetUniformValue( "uBlendColor", actualValue ) ); DALI_TEST_EQUALS( actualValue, Color::RED, TEST_LOCATION ); - bool isNewRenderer = factory.ResetRenderer( controlRenderer, Color::GREEN ); - DALI_TEST_CHECK( !isNewRenderer ); + factory.ResetRenderer( controlRenderer, actor, Color::GREEN ); application.SendNotification(); application.Render(0); DALI_TEST_CHECK( gl.GetUniformValue( "uBlendColor", actualValue ) ); DALI_TEST_EQUALS( actualValue, Color::GREEN, TEST_LOCATION ); Image bufferImage = CreateBufferImage( 100, 200, Vector4( 1.f, 1.f, 1.f, 1.f ) ); - isNewRenderer = factory.ResetRenderer( controlRenderer, bufferImage ); - DALI_TEST_CHECK( isNewRenderer ); + factory.ResetRenderer( controlRenderer, actor, bufferImage ); Actor actor2 = Actor::New(); actor2.SetSize(200.f, 200.f); @@ -832,13 +830,11 @@ int UtcDaliRendererFactoryResetRenderer2(void) application.Render(0); Image bufferImage = CreateBufferImage( 100, 200, Vector4( 1.f, 1.f, 1.f, 1.f ) ); - bool isNewRenderer = factory.ResetRenderer( controlRenderer, bufferImage ); - DALI_TEST_CHECK( !isNewRenderer ); + factory.ResetRenderer( controlRenderer, actor, bufferImage ); application.SendNotification(); application.Render(0); - isNewRenderer = factory.ResetRenderer( controlRenderer, Color::RED ); - DALI_TEST_CHECK( isNewRenderer ); + factory.ResetRenderer( controlRenderer, actor, Color::RED ); Actor actor2 = Actor::New(); actor2.SetSize(200.f, 200.f); diff --git a/dali-toolkit/devel-api/controls/renderer-factory/control-renderer.cpp b/dali-toolkit/devel-api/controls/renderer-factory/control-renderer.cpp index c036334..36e5c02 100644 --- a/dali-toolkit/devel-api/controls/renderer-factory/control-renderer.cpp +++ b/dali-toolkit/devel-api/controls/renderer-factory/control-renderer.cpp @@ -47,13 +47,13 @@ ControlRenderer& ControlRenderer::operator=( const ControlRenderer& handle ) } ControlRenderer::ControlRenderer(Internal::ControlRenderer *impl) -: BaseHandle(impl) +: BaseHandle( impl ) { } void ControlRenderer::SetSize( const Vector2& size ) { - GetImplementation( *this ).SetSize(size); + GetImplementation( *this ).SetSize( size ); } const Vector2& ControlRenderer::GetSize() const @@ -68,7 +68,7 @@ void ControlRenderer::GetNaturalSize(Vector2& naturalSize ) const void ControlRenderer::SetDepthIndex( float index ) { - GetImplementation( *this ).SetDepthIndex(index); + GetImplementation( *this ).SetDepthIndex( index ); } float ControlRenderer::GetDepthIndex() const @@ -78,12 +78,12 @@ float ControlRenderer::GetDepthIndex() const void ControlRenderer::SetOnStage( Actor& actor ) { - GetImplementation( *this ).SetOnStage(actor); + GetImplementation( *this ).SetOnStage( actor ); } void ControlRenderer::SetOffStage( Actor& actor ) { - GetImplementation( *this ).SetOffStage(actor); + GetImplementation( *this ).SetOffStage( actor ); } void ControlRenderer::RemoveAndReset( Actor& actor ) diff --git a/dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.cpp b/dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.cpp index 3f7ef6c..3ed8e73 100644 --- a/dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.cpp +++ b/dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.cpp @@ -92,9 +92,9 @@ ControlRenderer RendererFactory::GetControlRenderer( const Vector4& color ) return GetImplementation( *this ).GetControlRenderer( color ); } -bool RendererFactory::ResetRenderer( ControlRenderer& renderer, const Vector4& color ) +void RendererFactory::ResetRenderer( ControlRenderer& renderer, Actor& actor, const Vector4& color ) { - return GetImplementation( *this ).ResetRenderer( renderer, color ); + GetImplementation( *this ).ResetRenderer( renderer, actor, color ); } ControlRenderer RendererFactory::GetControlRenderer( float borderSize, const Vector4& borderColor ) @@ -107,9 +107,9 @@ ControlRenderer RendererFactory::GetControlRenderer( const Image& image ) return GetImplementation( *this ).GetControlRenderer( image ); } -bool RendererFactory::ResetRenderer( ControlRenderer& renderer, const Image& image ) +void RendererFactory::ResetRenderer( ControlRenderer& renderer, Actor& actor, const Image& image ) { - return GetImplementation( *this ).ResetRenderer( renderer, image ); + GetImplementation( *this ).ResetRenderer( renderer, actor, image ); } ControlRenderer RendererFactory::GetControlRenderer( const std::string& url ) @@ -117,14 +117,14 @@ ControlRenderer RendererFactory::GetControlRenderer( const std::string& url ) return GetImplementation( *this ).GetControlRenderer( url ); } -bool RendererFactory::ResetRenderer( ControlRenderer& renderer, const std::string& url ) +void RendererFactory::ResetRenderer( ControlRenderer& renderer, Actor& actor, const std::string& url ) { - return GetImplementation( *this ).ResetRenderer( renderer, url ); + GetImplementation( *this ).ResetRenderer( renderer, actor, url ); } -bool RendererFactory::ResetRenderer( ControlRenderer& renderer, const Property::Map& propertyMap ) +void RendererFactory::ResetRenderer( ControlRenderer& renderer, Actor& actor, const Property::Map& propertyMap ) { - return GetImplementation( *this ).ResetRenderer( renderer, propertyMap ); + GetImplementation( *this ).ResetRenderer( renderer, actor, propertyMap ); } } // namespace Toolkit diff --git a/dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.h b/dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.h index 13242f4..2e0c6c9 100644 --- a/dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.h +++ b/dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.h @@ -109,10 +109,10 @@ public: * else the renderer would be a handle to a newly created internal color renderer. * * @param[in] renderer The ControlRenderer to reset + * @param[in] actor The Actor the renderer is applied to if, empty if the renderer has not been applied to any Actor * @param[in] color The color to be rendered. - * @return Whether a new internal control renderer is created. */ - bool ResetRenderer( ControlRenderer& renderer, const Vector4& color ); + void ResetRenderer( ControlRenderer& renderer, Actor& actor, const Vector4& color ); /** * @brief Request the control renderer to renderer the border with the given size and color. @@ -138,10 +138,10 @@ public: * else the renderer would be a handle to a newly created internal image renderer. * * @param[in] renderer The ControlRenderer to reset + * @param[in] actor The Actor the renderer is applied to if, empty if the renderer has not been applied to any Actor * @param[in] image The Image to be rendered. - * @return Whether a new internal control renderer is created. */ - bool ResetRenderer( ControlRenderer& renderer, const Image& image ); + void ResetRenderer( ControlRenderer& renderer, Actor& actor, const Image& image ); /** * @brief Request the control renderer to render the given resource at the url. @@ -158,10 +158,10 @@ public: * else the renderer would be a handle to a newly created internal image renderer. * * @param[in] renderer The ControlRenderer to reset + * @param[in] actor The Actor the renderer is applied to if, empty if the renderer has not been applied to any Actor * @param[in] url The URL to the resource to be rendered. - * @return Whether a new internal control renderer is created. */ - bool ResetRenderer( ControlRenderer& renderer, const std::string& url ); + void ResetRenderer( ControlRenderer& renderer, Actor& actor, const std::string& url ); /** @@ -170,11 +170,12 @@ public: * if the current renderer is capable of merging with the property map the reset the renderer with the merged properties * else the renderer would be a handle to a newly created internal renderer. * + * @param[in] renderer The ControlRenderer to reset + * @param[in] actor The Actor the renderer is applied to if, empty if the renderer has not been applied to any Actor * @param[in] propertyMap The map contains the properties required by the control renderer * Depends on the content of the map, different kind of renderer would be returned. - * @return Whether a new internal control renderer is created. */ - bool ResetRenderer( ControlRenderer& renderer, const Property::Map& propertyMap ); + void ResetRenderer( ControlRenderer& renderer, Actor& actor, const Property::Map& propertyMap ); private: diff --git a/dali-toolkit/internal/controls/image-view/image-view-impl.cpp b/dali-toolkit/internal/controls/image-view/image-view-impl.cpp index 9f7294b..6f45e82 100644 --- a/dali-toolkit/internal/controls/image-view/image-view-impl.cpp +++ b/dali-toolkit/internal/controls/image-view/image-view-impl.cpp @@ -73,24 +73,8 @@ void ImageView::SetImage( Image image ) mImage = image; - bool newRendererCreated = false; - if( mRenderer ) - { - newRendererCreated = Toolkit::RendererFactory::Get().ResetRenderer( mRenderer, image ); - } - else - { - mRenderer = Toolkit::RendererFactory::Get().GetControlRenderer( image ); - newRendererCreated = true; - } - - //we need to inform any newly created renderers if it is on stage - if( newRendererCreated && Self().OnStage() ) - { - CustomActor self = Self(); - mRenderer.SetOnStage( self ); - } - + Actor self = Self(); + Toolkit::RendererFactory::Get().ResetRenderer( mRenderer, self, image ); mImageSize = image ? ImageDimensions( image.GetWidth(), image.GetHeight() ) : ImageDimensions( 0, 0 ); } } @@ -99,23 +83,8 @@ void ImageView::SetImage( Property::Map map ) { mPropertyMap = map; - bool newRendererCreated = false; - if( mRenderer ) - { - newRendererCreated = Toolkit::RendererFactory::Get().ResetRenderer( mRenderer, mPropertyMap ); - } - else - { - mRenderer = Toolkit::RendererFactory::Get().GetControlRenderer( mPropertyMap ); - newRendererCreated = true; - } - - //we need to inform any newly created renderers if it is on stage - CustomActor self = Self(); - if( newRendererCreated && self.OnStage() ) - { - mRenderer.SetOnStage( self ); - } + Actor self = Self(); + Toolkit::RendererFactory::Get().ResetRenderer( mRenderer, self, mPropertyMap ); int width = 0; Property::Value* widthValue = mPropertyMap.Find( "width" ); @@ -143,23 +112,8 @@ void ImageView::SetImage( const std::string& url ) mUrl = url; - bool newRendererCreated = false; - if( mRenderer ) - { - newRendererCreated = Toolkit::RendererFactory::Get().ResetRenderer( mRenderer, mUrl ); - } - else - { - mRenderer = Toolkit::RendererFactory::Get().GetControlRenderer( mUrl ); - newRendererCreated = true; - } - - //we need to inform any newly created renderers if it is on stage - if( newRendererCreated && Self().OnStage() ) - { - CustomActor self = Self(); - mRenderer.SetOnStage( self ); - } + Actor self = Self(); + Toolkit::RendererFactory::Get().ResetRenderer( mRenderer, self, mUrl ); mImageSize = ResourceImage::GetImageSize( mUrl ); } diff --git a/dali-toolkit/internal/controls/renderers/border/border-renderer.cpp b/dali-toolkit/internal/controls/renderers/border/border-renderer.cpp index ad46c2f..8e0d094 100644 --- a/dali-toolkit/internal/controls/renderers/border/border-renderer.cpp +++ b/dali-toolkit/internal/controls/renderers/border/border-renderer.cpp @@ -88,7 +88,7 @@ BorderRenderer::~BorderRenderer() { } -void BorderRenderer::DoInitialize( const Property::Map& propertyMap ) +void BorderRenderer::DoInitialize( Actor& actor, const Property::Map& propertyMap ) { Property::Value* color = propertyMap.Find( COLOR_NAME ); if( !( color && color->Get(mBorderColor) ) ) @@ -112,6 +112,8 @@ void BorderRenderer::SetClipRect( const Rect& clipRect ) void BorderRenderer::DoSetOnStage( Actor& actor ) { + InitializeRenderer(); + mBorderColorIndex = (mImpl->mRenderer).RegisterProperty( COLOR_UNIFORM_NAME, mBorderColor ); if( mBorderColor.a < 1.f ) { @@ -128,7 +130,7 @@ void BorderRenderer::DoCreatePropertyMap( Property::Map& map ) const map.Insert( SIZE_NAME, mBorderSize ); } -void BorderRenderer::InitializeRenderer( Renderer& renderer ) +void BorderRenderer::InitializeRenderer() { Geometry geometry = mFactoryCache.GetGeometry( RendererFactoryCache::BORDER_GEOMETRY ); if( !geometry ) @@ -144,27 +146,15 @@ void BorderRenderer::InitializeRenderer( Renderer& renderer ) mFactoryCache.SaveShader( RendererFactoryCache::COLOR_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 ); - } - } + Material material = Material::New( shader ); + mImpl->mRenderer = Renderer::New( geometry, material ); } void BorderRenderer::SetBorderColor(const Vector4& color) { mBorderColor = color; - if( mImpl->mIsOnStage ) + if( mImpl->mRenderer ) { (mImpl->mRenderer).SetProperty( mBorderColorIndex, color ); if( color.a < 1.f && (mImpl->mRenderer).GetMaterial().GetBlendMode() != BlendingMode::ON) @@ -178,7 +168,7 @@ void BorderRenderer::SetBorderSize( float size ) { mBorderSize = size; - if( mImpl->mIsOnStage ) + if( mImpl->mRenderer ) { (mImpl->mRenderer).SetProperty( mBorderSizeIndex, size ); } diff --git a/dali-toolkit/internal/controls/renderers/border/border-renderer.h b/dali-toolkit/internal/controls/renderers/border/border-renderer.h index 859cf01..37c59d2 100644 --- a/dali-toolkit/internal/controls/renderers/border/border-renderer.h +++ b/dali-toolkit/internal/controls/renderers/border/border-renderer.h @@ -71,12 +71,7 @@ protected: /** * @copydoc ControlRenderer::DoInitialize */ - virtual void DoInitialize( const Property::Map& propertyMap ); - - /** - * @copydoc ControlRenderer::InitializeRenderer - */ - virtual void InitializeRenderer( Renderer& renderer ); + virtual void DoInitialize( Actor& actor, const Property::Map& propertyMap ); /** * @copydoc ControlRenderer::DoSetOnStage @@ -105,6 +100,11 @@ public: private: /** + * @brief Initialize the renderer with the geometry and shader from the cache, if not available, create and save to the cache for sharing. + */ + void InitializeRenderer(); + + /** * Create the geometry which presents the border. * @return The border geometry */ diff --git a/dali-toolkit/internal/controls/renderers/color/color-renderer.cpp b/dali-toolkit/internal/controls/renderers/color/color-renderer.cpp index 4ca785d..5039c81 100644 --- a/dali-toolkit/internal/controls/renderers/color/color-renderer.cpp +++ b/dali-toolkit/internal/controls/renderers/color/color-renderer.cpp @@ -77,7 +77,7 @@ ColorRenderer::~ColorRenderer() { } -void ColorRenderer::DoInitialize( const Property::Map& propertyMap ) +void ColorRenderer::DoInitialize( Actor& actor, const Property::Map& propertyMap ) { Property::Value* color = propertyMap.Find( COLOR_NAME ); if( !( color && color->Get(mBlendColor) ) ) @@ -105,6 +105,11 @@ void ColorRenderer::SetOffset( const Vector2& offset ) //ToDo: renderer applies the offset } +void ColorRenderer::DoSetOnStage( Actor& actor ) +{ + InitializeRenderer(); +} + void ColorRenderer::DoCreatePropertyMap( Property::Map& map ) const { map.Clear(); @@ -112,7 +117,7 @@ void ColorRenderer::DoCreatePropertyMap( Property::Map& map ) const map.Insert( COLOR_NAME, mBlendColor ); } -void ColorRenderer::InitializeRenderer( Renderer& renderer ) +void ColorRenderer::InitializeRenderer() { Geometry geometry = mFactoryCache.GetGeometry( RendererFactoryCache::QUAD_GEOMETRY ); if( !geometry ) @@ -128,25 +133,13 @@ void ColorRenderer::InitializeRenderer( Renderer& renderer ) mFactoryCache.SaveShader( RendererFactoryCache::COLOR_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 ); - } - } + Material material = Material::New( shader ); + mImpl->mRenderer = Renderer::New( geometry, material ); - mBlendColorIndex = renderer.RegisterProperty( COLOR_UNIFORM_NAME, mBlendColor ); + mBlendColorIndex = mImpl->mRenderer.RegisterProperty( COLOR_UNIFORM_NAME, mBlendColor ); if( mBlendColor.a < 1.f ) { - renderer.GetMaterial().SetBlendMode( BlendingMode::ON ); + mImpl->mRenderer.GetMaterial().SetBlendMode( BlendingMode::ON ); } } @@ -154,7 +147,7 @@ void ColorRenderer::SetColor(const Vector4& color) { mBlendColor = color; - if( mImpl->mIsOnStage ) + if( mImpl->mRenderer ) { (mImpl->mRenderer).SetProperty( mBlendColorIndex, color ); if( color.a < 1.f && (mImpl->mRenderer).GetMaterial().GetBlendMode() != BlendingMode::ON) diff --git a/dali-toolkit/internal/controls/renderers/color/color-renderer.h b/dali-toolkit/internal/controls/renderers/color/color-renderer.h index 82071b5..70ad107 100644 --- a/dali-toolkit/internal/controls/renderers/color/color-renderer.h +++ b/dali-toolkit/internal/controls/renderers/color/color-renderer.h @@ -82,12 +82,12 @@ protected: /** * @copydoc ControlRenderer::DoInitialize */ - virtual void DoInitialize( const Property::Map& propertyMap ); + virtual void DoInitialize( Actor& actor, const Property::Map& propertyMap ); /** - * @copydoc ControlRenderer::InitializeRenderer + * @copydoc ControlRenderer::DoSetOnStage */ - virtual void InitializeRenderer( Renderer& renderer ); + virtual void DoSetOnStage( Actor& actor ); public: @@ -98,6 +98,12 @@ public: void SetColor( const Vector4& color ); private: + /** + * @brief Initialize the renderer with the geometry and shader from the cache, if not available, create and save to the cache for sharing. + */ + void InitializeRenderer(); + +private: // Undefined ColorRenderer( const ColorRenderer& colorRenderer ); diff --git a/dali-toolkit/internal/controls/renderers/control-renderer-data-impl.cpp b/dali-toolkit/internal/controls/renderers/control-renderer-data-impl.cpp index 6a58cfb..129ac03 100644 --- a/dali-toolkit/internal/controls/renderers/control-renderer-data-impl.cpp +++ b/dali-toolkit/internal/controls/renderers/control-renderer-data-impl.cpp @@ -88,7 +88,7 @@ Shader::ShaderHints HintFromString( std::string hintString ) Internal::ControlRenderer::Impl::Impl() : mCustomShader(NULL), mDepthIndex( 0.0f ), - mIsOnStage( false ) + mFlags( 0 ) { } diff --git a/dali-toolkit/internal/controls/renderers/control-renderer-data-impl.h b/dali-toolkit/internal/controls/renderers/control-renderer-data-impl.h index c616669..3a5ccbb 100644 --- a/dali-toolkit/internal/controls/renderers/control-renderer-data-impl.h +++ b/dali-toolkit/internal/controls/renderers/control-renderer-data-impl.h @@ -35,6 +35,12 @@ namespace Internal struct Internal::ControlRenderer::Impl { + enum Flags + { + IS_ON_STAGE = 1, + IS_FROM_CACHE = 1 << 1 + }; + struct CustomShader { std::string mVertexShader; @@ -47,7 +53,6 @@ struct Internal::ControlRenderer::Impl void CreatePropertyMap( Property::Map& map ) const; }; - std::string mCachedRendererKey; ///< The key to use for caching of the renderer. If it is empty then no caching will occur Renderer mRenderer; CustomShader* mCustomShader; @@ -56,7 +61,7 @@ struct Internal::ControlRenderer::Impl Vector2 mOffset; Rect mClipRect; float mDepthIndex; - bool mIsOnStage; + int mFlags; Impl(); ~Impl(); diff --git a/dali-toolkit/internal/controls/renderers/control-renderer-impl.cpp b/dali-toolkit/internal/controls/renderers/control-renderer-impl.cpp index 990182c..96f5066 100644 --- a/dali-toolkit/internal/controls/renderers/control-renderer-impl.cpp +++ b/dali-toolkit/internal/controls/renderers/control-renderer-impl.cpp @@ -56,7 +56,7 @@ ControlRenderer::~ControlRenderer() delete mImpl; } -void ControlRenderer::Initialize( const Property::Map& propertyMap ) +void ControlRenderer::Initialize( Actor& actor, const Property::Map& propertyMap ) { if( mImpl->mCustomShader ) { @@ -74,12 +74,7 @@ void ControlRenderer::Initialize( const Property::Map& propertyMap ) } } } - DoInitialize( propertyMap ); - - if( mImpl->mIsOnStage ) - { - InitializeRenderer( mImpl->mRenderer ); - } + DoInitialize( actor, propertyMap ); } void ControlRenderer::SetSize( const Vector2& size ) @@ -121,67 +116,24 @@ float ControlRenderer::GetDepthIndex() const return mImpl->mDepthIndex; } -void ControlRenderer::SetCachedRendererKey( const std::string& cachedRendererKey ) -{ - if( mImpl->mCachedRendererKey == cachedRendererKey ) - { - return; - } - if( !mImpl->mIsOnStage ) - { - mImpl->mCachedRendererKey = cachedRendererKey; - } - else - { - //clean the renderer from the cache since it may no longer be in use - mFactoryCache.CleanRendererCache( mImpl->mCachedRendererKey ); - - //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."); - mFactoryCache.SaveRenderer( mImpl->mCachedRendererKey, mImpl->mRenderer ); - } - } -} - void ControlRenderer::SetOnStage( Actor& actor ) { - if( !mImpl->mCachedRendererKey.empty() && !mImpl->mCustomShader ) - { - mImpl->mRenderer = mFactoryCache.GetRenderer( mImpl->mCachedRendererKey ); - if( !mImpl->mRenderer ) - { - InitializeRenderer( mImpl->mRenderer ); - mFactoryCache.SaveRenderer( mImpl->mCachedRendererKey, mImpl->mRenderer ); - } - } - - if( !mImpl->mRenderer ) - { - InitializeRenderer( mImpl->mRenderer ); - } + DoSetOnStage( actor ); mImpl->mRenderer.SetDepthIndex( mImpl->mDepthIndex ); actor.AddRenderer( mImpl->mRenderer ); - mImpl->mIsOnStage = true; - - DoSetOnStage( actor ); + mImpl->mFlags |= Impl::IS_ON_STAGE; } void ControlRenderer::SetOffStage( Actor& actor ) { - if( mImpl->mIsOnStage ) + if( GetIsOnStage() ) { DoSetOffStage( actor ); actor.RemoveRenderer( mImpl->mRenderer ); mImpl->mRenderer.Reset(); - //clean the renderer from the cache since it may no longer be in use - mFactoryCache.CleanRendererCache( mImpl->mCachedRendererKey ); - - mImpl->mIsOnStage = false; + mImpl->mFlags &= ~Impl::IS_ON_STAGE; } } @@ -202,6 +154,16 @@ void ControlRenderer::CreatePropertyMap( Property::Map& map ) const DoCreatePropertyMap( map ); } +bool ControlRenderer::GetIsOnStage() const +{ + return mImpl->mFlags & Impl::IS_ON_STAGE; +} + +bool ControlRenderer::GetIsFromCache() const +{ + return mImpl->mFlags & Impl::IS_FROM_CACHE; +} + } // namespace Internal } // namespace Toolkit diff --git a/dali-toolkit/internal/controls/renderers/control-renderer-impl.h b/dali-toolkit/internal/controls/renderers/control-renderer-impl.h index 10a13dc..7258e29 100644 --- a/dali-toolkit/internal/controls/renderers/control-renderer-impl.h +++ b/dali-toolkit/internal/controls/renderers/control-renderer-impl.h @@ -67,9 +67,10 @@ public: * 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] actor The Actor the renderer is applied to if, empty if the renderer has not been applied to any Actor * @param[in] propertyMap The properties for the requested ControlRenderer object. */ - void Initialize( const Property::Map& propertyMap ); + void Initialize( Actor& actor, const Property::Map& propertyMap ); /** * @copydoc Toolkit::ControlRenderer::SetSize @@ -156,17 +157,10 @@ protected: /** * @brief Called by Initialize() allowing sub classes to respond to the Initialize event * - * @param[in] factoryCache A pointer pointing to the RendererFactoryCache object + * @param[in] actor The Actor the renderer is applied to if, empty if the renderer has not been applied to any Actor * @param[in] propertyMap The properties for the requested ControlRenderer object. */ - 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; + virtual void DoInitialize( Actor& actor, const Property::Map& propertyMap ) = 0; protected: @@ -185,13 +179,19 @@ protected: virtual void DoSetOffStage( Actor& actor ); protected: + /** + * @brief Gets the on stage state for this ControlRenderer + * + * @return Returns true if this ControlRenderer is on stage, false if it is off the stage + */ + bool GetIsOnStage() const; /** - * @brief Sets the key to use for caching the renderer. If this is empty then no caching will occur + * @brief Gets whether the Dali::Renderer is from a shared cache (and therefore any modifications will affect other users of that renderer) * - * @param[in] cachedRendererKey The key to use for caching the renderer. + * @return Returns true if the renderer is from shared cache, false otherwise */ - void SetCachedRendererKey( const std::string& cachedRendererKey ); + bool GetIsFromCache() const; private: diff --git a/dali-toolkit/internal/controls/renderers/gradient/gradient-renderer.cpp b/dali-toolkit/internal/controls/renderers/gradient/gradient-renderer.cpp index 6dc25ca..00a6050 100644 --- a/dali-toolkit/internal/controls/renderers/gradient/gradient-renderer.cpp +++ b/dali-toolkit/internal/controls/renderers/gradient/gradient-renderer.cpp @@ -188,7 +188,7 @@ GradientRenderer::~GradientRenderer() { } -void GradientRenderer::DoInitialize( const Property::Map& propertyMap ) +void GradientRenderer::DoInitialize( Actor& actor, const Property::Map& propertyMap ) { Gradient::GradientUnits gradientUnits = Gradient::OBJECT_BOUNDING_BOX; Property::Value* unitsValue = propertyMap.Find( GRADIENT_UNITS_NAME ); @@ -234,6 +234,11 @@ void GradientRenderer::SetOffset( const Vector2& offset ) //ToDo: renderer applies the offset } +void GradientRenderer::DoSetOnStage( Actor& actor ) +{ + InitializeRenderer(); +} + void GradientRenderer::DoCreatePropertyMap( Property::Map& map ) const { map.Clear(); @@ -289,7 +294,7 @@ void GradientRenderer::DoCreatePropertyMap( Property::Map& map ) const } } -void GradientRenderer::InitializeRenderer( Dali::Renderer& renderer ) +void GradientRenderer::InitializeRenderer() { Geometry geometry = mFactoryCache.GetGeometry( RendererFactoryCache::QUAD_GEOMETRY ); if( !geometry ) @@ -308,20 +313,8 @@ void GradientRenderer::InitializeRenderer( Dali::Renderer& renderer ) } 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 ); - } - } + material = Material::New( shader ); + mImpl->mRenderer = Renderer::New( geometry, material ); Dali::BufferImage lookupTexture = mGradient->GenerateLookupTexture(); Sampler sampler = Sampler::New(); @@ -330,7 +323,7 @@ void GradientRenderer::InitializeRenderer( Dali::Renderer& renderer ) material.AddTexture( lookupTexture, UNIFORM_TEXTULRE_NAME, sampler ); - renderer.RegisterProperty( UNIFORM_ALIGNMENT_MATRIX_NAME, mGradientTransform ); + mImpl->mRenderer.RegisterProperty( UNIFORM_ALIGNMENT_MATRIX_NAME, mGradientTransform ); } bool GradientRenderer::NewGradient(Type gradientType, const Property::Map& propertyMap) diff --git a/dali-toolkit/internal/controls/renderers/gradient/gradient-renderer.h b/dali-toolkit/internal/controls/renderers/gradient/gradient-renderer.h index deed3aa..0747a1c 100644 --- a/dali-toolkit/internal/controls/renderers/gradient/gradient-renderer.h +++ b/dali-toolkit/internal/controls/renderers/gradient/gradient-renderer.h @@ -118,16 +118,21 @@ protected: /** * @copydoc ControlRenderer::DoInitialize */ - virtual void DoInitialize( const Property::Map& propertyMap ); + virtual void DoInitialize( Actor& actor, const Property::Map& propertyMap ); /** - * @copydoc ControlRenderer::InitializeRenderer + * @copydoc ControlRenderer::DoSetOnStage */ - virtual void InitializeRenderer( Renderer& renderer ); + virtual void DoSetOnStage( Actor& actor ); private: /** + * @brief Initialize the renderer with the geometry and shader from the cache, if not available, create and save to the cache for sharing. + */ + void InitializeRenderer(); + + /** * New a gradient object with the given property map. * * @return True if the property map provides valid properties to create a gradient. Otherwise, returns false. diff --git a/dali-toolkit/internal/controls/renderers/image/image-renderer.cpp b/dali-toolkit/internal/controls/renderers/image/image-renderer.cpp index 8f02d85..ea055a4 100644 --- a/dali-toolkit/internal/controls/renderers/image/image-renderer.cpp +++ b/dali-toolkit/internal/controls/renderers/image/image-renderer.cpp @@ -198,15 +198,16 @@ ImageRenderer::~ImageRenderer() { } -void ImageRenderer::DoInitialize( const Property::Map& propertyMap ) +void ImageRenderer::DoInitialize( Actor& actor, const Property::Map& propertyMap ) { + std::string oldImageUrl = mImageUrl; + Property::Value* imageURLValue = propertyMap.Find( IMAGE_URL_NAME ); if( imageURLValue ) { imageURLValue->Get( mImageUrl ); if( !mImageUrl.empty() ) { - SetCachedRendererKey( mImageUrl ); mImage.Reset(); } @@ -304,6 +305,37 @@ void ImageRenderer::DoInitialize( const Property::Map& propertyMap ) mDesiredSize = ImageDimensions( desiredWidth, desiredHeight ); } + + if( mImpl->mRenderer ) + { + //remove old renderer + if( actor ) + { + actor.RemoveRenderer( mImpl->mRenderer ); + } + + //clean the cache + if( !oldImageUrl.empty() ) + { + mFactoryCache.CleanRendererCache( oldImageUrl ); + } + + //Initialize the renderer + if( !mImageUrl.empty() ) + { + InitializeRenderer( mImageUrl ); + } + else if( mImage ) + { + InitializeRenderer( mImage ); + } + + //add the new renderer to the actor + if( actor && mImpl->mRenderer ) + { + actor.AddRenderer( mImpl->mRenderer ); + } + } } void ImageRenderer::SetSize( const Vector2& size ) @@ -345,14 +377,14 @@ void ImageRenderer::SetOffset( const Vector2& offset ) { } -void ImageRenderer::InitializeRenderer( Renderer& renderer ) +Renderer ImageRenderer::CreateRenderer() const { Geometry geometry; Shader shader; + if( !mImpl->mCustomShader ) { geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) ); - shader = mFactoryCache.GetShader( RendererFactoryCache::IMAGE_SHADER ); if( !shader ) { @@ -363,7 +395,6 @@ void ImageRenderer::InitializeRenderer( Renderer& renderer ) else { geometry = CreateGeometry( mFactoryCache, mImpl->mCustomShader->mGridSize ); - if( mImpl->mCustomShader->mVertexShader.empty() && mImpl->mCustomShader->mFragmentShader.empty() ) { shader = mFactoryCache.GetShader( RendererFactoryCache::IMAGE_SHADER ); @@ -381,33 +412,82 @@ void ImageRenderer::InitializeRenderer( Renderer& renderer ) } } - if( !renderer ) + Material material = Material::New( shader ); + return Renderer::New( geometry, material ); +} + +void ImageRenderer::InitializeRenderer( const std::string& imageUrl ) +{ + if( mImageUrl.empty() ) { - Material material = Material::New( shader ); - renderer = Renderer::New( geometry, material ); + mImpl->mFlags &= ~Impl::IS_FROM_CACHE; + return; } - else + + mImpl->mRenderer.Reset(); + if( !mImpl->mCustomShader ) { - renderer.SetGeometry( geometry ); - Material material = renderer.GetMaterial(); - if( material ) + mImpl->mRenderer = mFactoryCache.GetRenderer( imageUrl ); + if( !mImpl->mRenderer ) { - material.SetShader( shader ); + mImpl->mRenderer = CreateRenderer(); + + ResourceImage image = Dali::ResourceImage::New( imageUrl ); + image.LoadingFinishedSignal().Connect( this, &ImageRenderer::OnImageLoaded ); + Material material = mImpl->mRenderer.GetMaterial(); + material.AddTexture( image, TEXTURE_UNIFORM_NAME ); + + mFactoryCache.SaveRenderer( imageUrl, mImpl->mRenderer ); } + mImpl->mFlags |= Impl::IS_FROM_CACHE; + } + else + { + mImpl->mFlags &= ~Impl::IS_FROM_CACHE; + mImpl->mRenderer = CreateRenderer(); + ResourceImage image = Dali::ResourceImage::New( imageUrl, mDesiredSize, mFittingMode, mSamplingMode ); + image.LoadingFinishedSignal().Connect( this, &ImageRenderer::OnImageLoaded ); + ApplyImageToSampler( image ); } } -void ImageRenderer::DoSetOnStage( Actor& actor ) +void ImageRenderer::InitializeRenderer( const Image& image ) { - if( !mImageUrl.empty() && !mImage ) + mImpl->mFlags &= ~Impl::IS_FROM_CACHE; + + if( !image ) { - Dali::ResourceImage resourceImage = Dali::ResourceImage::New( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode ); - resourceImage.LoadingFinishedSignal().Connect( this, &ImageRenderer::OnImageLoaded ); + return; + } + + mImpl->mRenderer = CreateRenderer(); + ApplyImageToSampler( image ); +} - mImage = resourceImage; + +void ImageRenderer::DoSetOnStage( Actor& actor ) +{ + if( !mImageUrl.empty() ) + { + InitializeRenderer( mImageUrl ); } + else if( mImage ) + { + InitializeRenderer( mImage ); + } + + if( !GetIsFromCache() ) + { + Image image = mImage; + if( !mImageUrl.empty() ) + { + ResourceImage resourceImage = Dali::ResourceImage::New( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode ); + resourceImage.LoadingFinishedSignal().Connect( this, &ImageRenderer::OnImageLoaded ); + image = resourceImage; + } - ApplyImageToSampler(); + ApplyImageToSampler( image ); + } } void ImageRenderer::DoSetOffStage( Actor& actor ) @@ -415,6 +495,9 @@ void ImageRenderer::DoSetOffStage( Actor& actor ) //If we own the image then make sure we release it when we go off stage if( !mImageUrl.empty() ) { + //clean the renderer from the cache since it may no longer be in use + mFactoryCache.CleanRendererCache( mImageUrl ); + mImage.Reset(); } } @@ -515,73 +598,114 @@ void ImageRenderer::DoCreatePropertyMap( Property::Map& map ) const } } -void ImageRenderer::SetImage( const std::string& imageUrl ) +void ImageRenderer::SetImage( Actor& actor, const std::string& imageUrl ) { - SetImage( imageUrl, 0, 0, Dali::FittingMode::DEFAULT, Dali::SamplingMode::DEFAULT ); + SetImage( actor, imageUrl, 0, 0, Dali::FittingMode::DEFAULT, Dali::SamplingMode::DEFAULT ); } -void ImageRenderer::SetImage( const std::string& imageUrl, int desiredWidth, int desiredHeight, Dali::FittingMode::Type fittingMode, Dali::SamplingMode::Type samplingMode ) +void ImageRenderer::SetImage( Actor& actor, const std::string& imageUrl, int desiredWidth, int desiredHeight, Dali::FittingMode::Type fittingMode, Dali::SamplingMode::Type samplingMode ) { if( mImageUrl != imageUrl ) { + if( mImpl->mRenderer ) + { + if( GetIsFromCache() ) + { + //remove old renderer + if( actor ) + { + actor.RemoveRenderer( mImpl->mRenderer ); + } + + //clean the cache + if( !mImageUrl.empty() ) + { + mFactoryCache.CleanRendererCache( mImageUrl ); + } + + //Initialize the renderer + InitializeRenderer( imageUrl ); + + //add the new renderer to the actor + if( actor && mImpl->mRenderer ) + { + actor.AddRenderer( mImpl->mRenderer ); + } + } + else + { + ResourceImage image = Dali::ResourceImage::New( imageUrl, mDesiredSize, mFittingMode, mSamplingMode ); + image.LoadingFinishedSignal().Connect( this, &ImageRenderer::OnImageLoaded ); + ApplyImageToSampler( image ); + } + } + mImageUrl = imageUrl; - SetCachedRendererKey( mImageUrl ); mDesiredSize = ImageDimensions( desiredWidth, desiredHeight ); mFittingMode = fittingMode; mSamplingMode = samplingMode; - - if( !mImageUrl.empty() && mImpl->mIsOnStage ) - { - Dali::ResourceImage resourceImage = Dali::ResourceImage::New( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode ); - resourceImage.LoadingFinishedSignal().Connect( this, &ImageRenderer::OnImageLoaded ); - mImage = resourceImage; - - ApplyImageToSampler(); - } - else - { - mImage.Reset(); - } + mImage.Reset(); } } -void ImageRenderer::SetImage( Image image ) +void ImageRenderer::SetImage( Actor& actor, const Image& image ) { if( mImage != image ) { + if( mImpl->mRenderer ) + { + if( GetIsFromCache() ) + { + //remove old renderer + if( actor ) + { + actor.RemoveRenderer( mImpl->mRenderer ); + } + + //clean the cache + if( !mImageUrl.empty() ) + { + mFactoryCache.CleanRendererCache( mImageUrl ); + } + + //Initialize the renderer + InitializeRenderer( image ); + + //add the new renderer to the actor + if( actor && mImpl->mRenderer ) + { + actor.AddRenderer( mImpl->mRenderer ); + } + } + else + { + ApplyImageToSampler( image ); + } + } + + mImage = image; mImageUrl.clear(); mDesiredSize = ImageDimensions(); mFittingMode = FittingMode::DEFAULT; mSamplingMode = SamplingMode::DEFAULT; - mImage = image; - - if( mImage && mImpl->mIsOnStage ) - { - ApplyImageToSampler(); - } } } -Image ImageRenderer::GetImage() const -{ - return mImage; -} - -void ImageRenderer::ApplyImageToSampler() +void ImageRenderer::ApplyImageToSampler( const Image& image ) { - if( mImage ) + if( image ) { Material material = mImpl->mRenderer.GetMaterial(); if( material ) { - int index = material.GetTextureIndex(TEXTURE_UNIFORM_NAME); + int index = material.GetTextureIndex( TEXTURE_UNIFORM_NAME ); if( index != -1 ) { - material.SetTextureImage( index, mImage ); + material.SetTextureImage( index, image ); return; } - material.AddTexture( mImage,TEXTURE_UNIFORM_NAME ); + material.AddTexture( image, TEXTURE_UNIFORM_NAME ); } } } @@ -590,10 +714,10 @@ void ImageRenderer::OnImageLoaded( ResourceImage image ) { if( image.GetLoadingState() == Dali::ResourceLoadingFailed ) { - mImage = RendererFactory::GetBrokenRendererImage(); - if( mImpl->mIsOnStage ) + Image image = RendererFactory::GetBrokenRendererImage(); + if( mImpl->mRenderer ) { - ApplyImageToSampler(); + ApplyImageToSampler( image ); } } } diff --git a/dali-toolkit/internal/controls/renderers/image/image-renderer.h b/dali-toolkit/internal/controls/renderers/image/image-renderer.h index efcbf53..e01efd0 100644 --- a/dali-toolkit/internal/controls/renderers/image/image-renderer.h +++ b/dali-toolkit/internal/controls/renderers/image/image-renderer.h @@ -116,7 +116,7 @@ protected: /** * @copydoc ControlRenderer::DoInitialize */ - virtual void DoInitialize( const Property::Map& propertyMap ); + virtual void DoInitialize( Actor& actor, const Property::Map& propertyMap ); /** * @copydoc ControlRenderer::DoSetOnStage @@ -128,53 +128,67 @@ protected: */ virtual void DoSetOffStage( Actor& actor ); - /** - * @copydoc ControlRenderer::InitializeRenderer - */ - virtual void InitializeRenderer( Renderer& renderer ); - public: /** * @brief Sets the image of this renderer to the resource at imageUrl * The renderer will load the Image asynchronously when the associated actor is put on stage, and destroy the image when it is off stage * + * @param[in] actor The Actor the renderer is applied to if, empty if the renderer has not been applied to any Actor * @param[in] imageUrl The URL to to image resource to use */ - void SetImage( const std::string& imageUrl ); + void SetImage( Actor& actor, const std::string& imageUrl ); /** * @brief Sets the image of this renderer to the resource at imageUrl * The renderer will load the Image asynchronously when the associated actor is put on stage, and destroy the image when it is off stage * + * @param[in] actor The Actor the renderer is applied to if, empty if the renderer has not been applied to any Actor * @param[in] imageUrl The URL to to image resource to use * @param[in] desiredWidth The desired width of the resource to load * @param[in] desiredHeight The desired height of the resource to load * @param[in] fittingMode The FittingMode of the resource to load * @param[in] samplingMode The SamplingMode of the resource to load */ - void SetImage( const std::string& imageUrl, int desiredWidth, int desiredHeight, Dali::FittingMode::Type fittingMode, Dali::SamplingMode::Type samplingMode ); + void SetImage( Actor& actor, const std::string& imageUrl, int desiredWidth, int desiredHeight, Dali::FittingMode::Type fittingMode, Dali::SamplingMode::Type samplingMode ); /** * @brief Sets the image of this renderer to use * + * @param[in] actor The Actor the renderer is applied to if, empty if the renderer has not been applied to any Actor * @param[in] image The image to use */ - void SetImage( Image image ); + void SetImage( Actor& actor, const Image& image ); + +private: /** - * @brief Gets the image this renderer uses + * @brief Applies the image to the material used for this renderer * - * @return The image this renderer uses, which may be null if the image is set from a URL string and the renderer is not set as onstage + * @param[in] image The Image to apply to the material used for this renderer */ - Image GetImage() const; + void ApplyImageToSampler( const Image& image ); -private: + /** + * @brief Initializes the Dali::Renderer from an image url string + * + * @param[in] imageUrl The image url string to intialize this ImageRenderer from + */ + void InitializeRenderer( const std::string& imageUrl ); /** - * @brief Applies this renderer's image to the sampler to the material used for this renderer + * @brief Initializes the Dali::Renderer from an image handle + * + * @param[in] image The image handle to intialize this ImageRenderer from + */ + void InitializeRenderer( const Image& image ); + + /** + * @brief Creates the Dali::Renderer (potentially from the renderer cache), initializing it + * + * @return Returns the created Dali::Renderer */ - void ApplyImageToSampler(); + Renderer CreateRenderer() const; /** * Callback function of image resource loading succeed diff --git a/dali-toolkit/internal/controls/renderers/npatch/npatch-renderer.cpp b/dali-toolkit/internal/controls/renderers/npatch/npatch-renderer.cpp index 8e509a9..64a1763 100644 --- a/dali-toolkit/internal/controls/renderers/npatch/npatch-renderer.cpp +++ b/dali-toolkit/internal/controls/renderers/npatch/npatch-renderer.cpp @@ -217,7 +217,7 @@ NPatchRenderer::~NPatchRenderer() { } -void NPatchRenderer::DoInitialize( const Property::Map& propertyMap ) +void NPatchRenderer::DoInitialize( Actor& actor, const Property::Map& propertyMap ) { Property::Value* imageURLValue = propertyMap.Find( IMAGE_URL_NAME ); if( imageURLValue ) @@ -272,10 +272,9 @@ void NPatchRenderer::SetOffset( const Vector2& offset ) //ToDo: renderer applies the offset } -void NPatchRenderer::InitializeRenderer( Renderer& renderer ) +Geometry NPatchRenderer::CreateGeometry() { Geometry geometry; - Shader shader; if( mStretchPixelsX.Size() == 1 && mStretchPixelsY.Size() == 1 ) { if( !mBorderOnly ) @@ -296,7 +295,21 @@ void NPatchRenderer::InitializeRenderer( Renderer& renderer ) mFactoryCache.SaveGeometry( RendererFactoryCache::NINE_PATCH_BORDER_GEOMETRY, geometry ); } } + } + else if( mStretchPixelsX.Size() > 0 || mStretchPixelsY.Size() > 0) + { + Uint16Pair gridSize( 2 * mStretchPixelsX.Size() + 1, 2 * mStretchPixelsY.Size() + 1 ); + geometry = !mBorderOnly ? CreateGeometry( gridSize ) : CreateGeometryBorder( gridSize ); + } + + return geometry; +} +Shader NPatchRenderer::CreateShader() +{ + Shader shader; + if( mStretchPixelsX.Size() == 1 && mStretchPixelsY.Size() == 1 ) + { shader = mFactoryCache.GetShader( RendererFactoryCache::NINE_PATCH_SHADER ); if( !shader ) { @@ -306,9 +319,6 @@ void NPatchRenderer::InitializeRenderer( Renderer& renderer ) } else if( mStretchPixelsX.Size() > 0 || mStretchPixelsY.Size() > 0) { - Uint16Pair gridSize( 2 * mStretchPixelsX.Size() + 1, 2 * mStretchPixelsY.Size() + 1 ); - geometry = !mBorderOnly ? CreateGeometry( gridSize ) : CreateGeometryBorder( gridSize ); - std::stringstream vertexShader; vertexShader << "#define FACTOR_SIZE_X " << mStretchPixelsX.Size() + 2 << "\n" << "#define FACTOR_SIZE_Y " << mStretchPixelsY.Size() + 2 << "\n" @@ -316,28 +326,25 @@ void NPatchRenderer::InitializeRenderer( Renderer& renderer ) shader = Shader::New( vertexShader.str(), FRAGMENT_SHADER ); } - else + return shader; +} + +void NPatchRenderer::InitializeRenderer() +{ + Geometry geometry = CreateGeometry(); + Shader shader = CreateShader(); + + if( !geometry || !shader ) { DALI_LOG_ERROR("The 9 patch image '%s' doesn't have any valid stretch borders and so is not a valid 9 patch image\n", mImageUrl.c_str() ); InitializeFromBrokenImage(); } - 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 ); - } - } + Material material = Material::New( shader ); + mImpl->mRenderer = Renderer::New( geometry, material ); } + void NPatchRenderer::DoSetOnStage( Actor& actor ) { if( !mCroppedImage ) @@ -351,10 +358,11 @@ void NPatchRenderer::DoSetOnStage( Actor& actor ) { InitializeFromImage( mImage ); } - - InitializeRenderer( mImpl->mRenderer ); } + //initialize the renderer after initializing from the image since we need to know the grid size from the image before creating the geometry + InitializeRenderer(); + if( mCroppedImage ) { ApplyImageToSampler(); @@ -381,8 +389,52 @@ void NPatchRenderer::DoCreatePropertyMap( Property::Map& map ) const map.Insert( BORDER_ONLY, mBorderOnly ); } +void NPatchRenderer::ChangeRenderer( bool oldBorderOnly, size_t oldGridX, size_t oldGridY ) +{ + //check to see if the border style has changed + + bool borderOnlyChanged = oldBorderOnly != mBorderOnly; + bool gridChanged = oldGridX != mStretchPixelsX.Size() || oldGridY != mStretchPixelsY.Size(); + + if( borderOnlyChanged || gridChanged ) + { + Geometry geometry = CreateGeometry(); + if( geometry ) + { + mImpl->mRenderer.SetGeometry( geometry ); + } + else + { + InitializeFromBrokenImage(); + } + } + + if( gridChanged ) + { + Shader shader = CreateShader(); + Material material; + if( shader ) + { + material = mImpl->mRenderer.GetMaterial(); + if( material ) + { + material.SetShader( shader ); + } + } + + if( !material ) + { + InitializeFromBrokenImage(); + } + } +} + void NPatchRenderer::SetImage( const std::string& imageUrl, bool borderOnly ) { + bool oldBorderOnly = mBorderOnly; + size_t oldGridX = mStretchPixelsX.Size(); + size_t oldGridY = mStretchPixelsY.Size(); + mBorderOnly = borderOnly; mImage.Reset(); if( mImageUrl == imageUrl ) @@ -391,17 +443,26 @@ void NPatchRenderer::SetImage( const std::string& imageUrl, bool borderOnly ) } mImageUrl = imageUrl; - NinePatchImage nPatch = NinePatchImage::New( mImageUrl ); - InitializeFromImage( nPatch ); - - if( mCroppedImage && mImpl->mIsOnStage ) + if( mImpl->mRenderer ) { - ApplyImageToSampler(); + NinePatchImage nPatch = NinePatchImage::New( mImageUrl ); + InitializeFromImage( nPatch ); + + ChangeRenderer( oldBorderOnly, oldGridX, oldGridY ); + + if( mCroppedImage ) + { + ApplyImageToSampler(); + } } } void NPatchRenderer::SetImage( NinePatchImage image, bool borderOnly ) { + bool oldBorderOnly = mBorderOnly; + size_t oldGridX = mStretchPixelsX.Size(); + size_t oldGridY = mStretchPixelsY.Size(); + mBorderOnly = borderOnly; mImageUrl.empty(); if( mImage == image ) @@ -410,11 +471,15 @@ void NPatchRenderer::SetImage( NinePatchImage image, bool borderOnly ) } mImage = image; - InitializeFromImage( mImage ); - - if( mCroppedImage && mImpl->mIsOnStage ) + if( mImpl->mRenderer ) { - ApplyImageToSampler(); + InitializeFromImage( mImage ); + ChangeRenderer( oldBorderOnly, oldGridX, oldGridY ); + + if( mCroppedImage ) + { + ApplyImageToSampler(); + } } } diff --git a/dali-toolkit/internal/controls/renderers/npatch/npatch-renderer.h b/dali-toolkit/internal/controls/renderers/npatch/npatch-renderer.h index c17b167..0844e7b 100644 --- a/dali-toolkit/internal/controls/renderers/npatch/npatch-renderer.h +++ b/dali-toolkit/internal/controls/renderers/npatch/npatch-renderer.h @@ -92,12 +92,7 @@ protected: /** * @copydoc ControlRenderer::DoInitialize */ - virtual void DoInitialize( const Property::Map& propertyMap ); - - /** - * @copydoc ControlRenderer::InitializeRenderer - */ - virtual void InitializeRenderer( Renderer& renderer ); + virtual void DoInitialize( Actor& actor, const Property::Map& propertyMap ); /** * @copydoc ControlRenderer::DoSetOnStage @@ -131,9 +126,28 @@ public: private: /** + * @brief Initialize the renderer with the geometry and shader from the cache, if not available, create and save to the cache for sharing. + */ + void InitializeRenderer(); + + /** + * @brief Creates a geometry for this renderer's grid size + * + * @return Returns the created geometry for this renderer's grid size + */ + Geometry CreateGeometry(); + + /** + * @brief Creates a shader for this renderer's grid size + * + * @return Returns the created shader for this renderer's grid size + */ + Shader CreateShader(); + + /** * @brief Creates a geometry for the grid size to be used by this renderers' shaders * - * @param gridSize The grid size of the solid geometry to create + * @param[in] gridSize The grid size of the solid geometry to create * @return Returns the created geometry for the grid size */ Geometry CreateGeometry( Uint16Pair gridSize ); @@ -156,7 +170,7 @@ private: * |/ |/ |/ |/ |/ | * --------------------- * - * @param gridSize The grid size of the solid geometry to create + * @param[in] gridSize The grid size of the solid geometry to create * @return Returns the created geometry for the grid size */ Geometry CreateGeometryBorder( Uint16Pair gridSize ); @@ -164,7 +178,7 @@ private: /** * @brief Creates Image from the image url and parses the image for the stretch borders. Will create a error image if the n patch image is invalid * - * @param nPatchImage The NinePatchImage to base our cropped images and stretch borders from + * @param[in] nPatchImage The NinePatchImage to base our cropped images and stretch borders from */ void InitializeFromImage( NinePatchImage nPatchImage ); @@ -179,6 +193,15 @@ private: */ void ApplyImageToSampler(); + /** + * @brief Changes the current renderer if the n-patch meta data has changed + * + * @param[in] oldBorderOnly The old flag indicating if the image should omit the centre of the n-patch and only render the border + * @param[in] oldGridX The old horizontal grid size of the solid geometry + * @param[in] oldGridY The old vertical grid size of the solid geometry + */ + void ChangeRenderer( bool oldBorderOnly, size_t oldGridX, size_t oldGridY ); + private: NinePatchImage mImage; ///< The image to render if the renderer was set from an NinePatchImage, empty otherwise diff --git a/dali-toolkit/internal/controls/renderers/renderer-factory-impl.cpp b/dali-toolkit/internal/controls/renderers/renderer-factory-impl.cpp index ddac18e..a91aa71 100644 --- a/dali-toolkit/internal/controls/renderers/renderer-factory-impl.cpp +++ b/dali-toolkit/internal/controls/renderers/renderer-factory-impl.cpp @@ -114,7 +114,8 @@ Toolkit::ControlRenderer RendererFactory::GetControlRenderer( const Property::Ma if( rendererPtr ) { - rendererPtr->Initialize( propertyMap ); + Actor actor; + rendererPtr->Initialize( actor, propertyMap ); } else { @@ -137,18 +138,22 @@ Toolkit::ControlRenderer RendererFactory::GetControlRenderer( const Vector4& col return Toolkit::ControlRenderer( rendererPtr ); } -bool RendererFactory::ResetRenderer( Toolkit::ControlRenderer& renderer, const Vector4& color ) +void RendererFactory::ResetRenderer( Toolkit::ControlRenderer& renderer, Actor& actor, const Vector4& color ) { ColorRenderer* rendererPtr = dynamic_cast< ColorRenderer* >( &GetImplementation( renderer ) ); if( rendererPtr ) { rendererPtr->SetColor( color ); - return false; } else { + renderer.RemoveAndReset( actor ); renderer = GetControlRenderer( color ); - return true; + + if( actor.OnStage() ) + { + renderer.SetOnStage( actor ); + } } } @@ -189,36 +194,44 @@ Toolkit::ControlRenderer RendererFactory::GetControlRenderer( const Image& image else { ImageRenderer* rendererPtr = new ImageRenderer( *( mFactoryCache.Get() ) ); - rendererPtr->SetImage( image ); + Actor actor; + rendererPtr->SetImage( actor, image ); return Toolkit::ControlRenderer( rendererPtr ); } } -bool RendererFactory::ResetRenderer( Toolkit::ControlRenderer& renderer, const Image& image ) +void RendererFactory::ResetRenderer( Toolkit::ControlRenderer& renderer, Actor& actor, const Image& image ) { - NinePatchImage npatchImage = NinePatchImage::DownCast( image ); - if( npatchImage ) + if( renderer ) { - NPatchRenderer* rendererPtr = dynamic_cast< NPatchRenderer* >( &GetImplementation( renderer ) ); - if( rendererPtr ) + NinePatchImage npatchImage = NinePatchImage::DownCast( image ); + if( npatchImage ) { - rendererPtr->SetImage( npatchImage ); - return false; + NPatchRenderer* rendererPtr = dynamic_cast< NPatchRenderer* >( &GetImplementation( renderer ) ); + if( rendererPtr ) + { + rendererPtr->SetImage( npatchImage ); + return; + } } - } - else - { - ImageRenderer* rendererPtr = dynamic_cast< ImageRenderer* >( &GetImplementation( renderer ) ); - if( rendererPtr ) + else { - rendererPtr->SetImage( image ); - return false; + ImageRenderer* rendererPtr = dynamic_cast< ImageRenderer* >( &GetImplementation( renderer ) ); + if( rendererPtr ) + { + rendererPtr->SetImage( actor, image ); + return; + } } } + renderer.RemoveAndReset( actor ); renderer = GetControlRenderer( image ); - return true; + if( actor.OnStage() ) + { + renderer.SetOnStage( actor ); + } } Toolkit::ControlRenderer RendererFactory::GetControlRenderer( const std::string& url ) @@ -238,75 +251,88 @@ Toolkit::ControlRenderer RendererFactory::GetControlRenderer( const std::string& else { ImageRenderer* rendererPtr = new ImageRenderer( *( mFactoryCache.Get() ) ); - rendererPtr->SetImage( url ); + Actor actor; + rendererPtr->SetImage( actor, url ); return Toolkit::ControlRenderer( rendererPtr ); } } -bool RendererFactory::ResetRenderer( Toolkit::ControlRenderer& renderer, const std::string& url ) +void RendererFactory::ResetRenderer( Toolkit::ControlRenderer& renderer, Actor& actor, const std::string& url ) { - if( NinePatchImage::IsNinePatchUrl( url ) ) + if( renderer ) { - NPatchRenderer* rendererPtr = dynamic_cast< NPatchRenderer* >( &GetImplementation( renderer ) ); - if( rendererPtr ) + if( NinePatchImage::IsNinePatchUrl( url ) ) { - rendererPtr->SetImage( url ); - return false; + NPatchRenderer* rendererPtr = dynamic_cast< NPatchRenderer* >( &GetImplementation( renderer ) ); + if( rendererPtr ) + { + rendererPtr->SetImage( url ); + return; + } } - } - else - { - ImageRenderer* rendererPtr = dynamic_cast< ImageRenderer* >( &GetImplementation( renderer ) ); - if( rendererPtr ) + else { - rendererPtr->SetImage( url ); - return false; + ImageRenderer* rendererPtr = dynamic_cast< ImageRenderer* >( &GetImplementation( renderer ) ); + if( rendererPtr ) + { + rendererPtr->SetImage( actor, url ); + return; + } } } + renderer.RemoveAndReset( actor ); + renderer = GetControlRenderer( url ); + if( actor.OnStage() ) { - renderer = GetControlRenderer( url ); - return true; + renderer.SetOnStage( actor ); } } -bool RendererFactory::ResetRenderer( Toolkit::ControlRenderer& renderer, const Property::Map& propertyMap ) +void RendererFactory::ResetRenderer( Toolkit::ControlRenderer& renderer, Actor& actor, const Property::Map& propertyMap ) { - Property::Value* type = propertyMap.Find( RENDERER_TYPE_NAME ); - std::string typeValue ; - if( type && type->Get( typeValue )) + if( renderer ) { - //If there's been a renderer type change then we have to return a new shader - if( typeValue == COLOR_RENDERER && typeid( renderer ) != typeid( ColorRenderer ) ) - { - renderer = GetControlRenderer( propertyMap ); - return true; - } - else if( typeValue == GRADIENT_RENDERER && typeid( renderer ) != typeid( GradientRenderer ) ) - { - renderer = GetControlRenderer( propertyMap ); - return true; - } - else if( typeValue == IMAGE_RENDERER && typeid( renderer ) != typeid( ImageRenderer ) ) + Property::Value* type = propertyMap.Find( RENDERER_TYPE_NAME ); + std::string typeValue ; + if( type && type->Get( typeValue )) { - renderer = GetControlRenderer( propertyMap ); - return true; - } - else if( typeValue == N_PATCH_RENDERER && typeid( renderer ) != typeid( NPatchRenderer ) ) - { - renderer = GetControlRenderer( propertyMap ); - return true; - } - else if( typeValue == BORDER_RENDERER && typeid( renderer ) != typeid( BorderRenderer ) ) - { - renderer = GetControlRenderer( propertyMap ); - return true; + //If there's been a renderer type change then we have to return a new shader + if( typeValue == COLOR_RENDERER && typeid( renderer ) != typeid( ColorRenderer ) ) + { + renderer = GetControlRenderer( propertyMap ); + return; + } + else if( typeValue == GRADIENT_RENDERER && typeid( renderer ) != typeid( GradientRenderer ) ) + { + renderer = GetControlRenderer( propertyMap ); + return; + } + else if( typeValue == IMAGE_RENDERER && typeid( renderer ) != typeid( ImageRenderer ) ) + { + renderer = GetControlRenderer( propertyMap ); + return; + } + else if( typeValue == N_PATCH_RENDERER && typeid( renderer ) != typeid( NPatchRenderer ) ) + { + renderer = GetControlRenderer( propertyMap ); + return; + } + else if( typeValue == BORDER_RENDERER && typeid( renderer ) != typeid( BorderRenderer ) ) + { + renderer = GetControlRenderer( propertyMap ); + return; + } } + + GetImplementation( renderer ).Initialize( actor, propertyMap ); + } + else + { + renderer = GetControlRenderer( propertyMap ); } - GetImplementation( renderer ).Initialize( propertyMap ); - return false; } Image RendererFactory::GetBrokenRendererImage() diff --git a/dali-toolkit/internal/controls/renderers/renderer-factory-impl.h b/dali-toolkit/internal/controls/renderers/renderer-factory-impl.h index a76c572..fed299a 100644 --- a/dali-toolkit/internal/controls/renderers/renderer-factory-impl.h +++ b/dali-toolkit/internal/controls/renderers/renderer-factory-impl.h @@ -55,9 +55,9 @@ public: Toolkit::ControlRenderer GetControlRenderer( const Property::Map& propertyMap ); /** - * @copydoc Toolkit::RenderFactory::ResetRenderer( Toolkit::ControlRenderer& renderer, const Property::Map& propertyMap ) + * @copydoc Toolkit::RenderFactory::ResetRenderer( Toolkit::ControlRenderer& renderer, Actor& actor, const Property::Map& propertyMap ) */ - bool ResetRenderer( Toolkit::ControlRenderer& renderer, const Property::Map& propertyMap ); + void ResetRenderer( Toolkit::ControlRenderer& renderer, Actor& actor, const Property::Map& propertyMap ); /** * @copydoc Toolkit::RenderFactory::GetControlRenderer( const Vector4& ) @@ -65,9 +65,9 @@ public: Toolkit::ControlRenderer GetControlRenderer( const Vector4& color ); /** - * @copydoc Toolkit::RendererFactory::ResetRenderer( Toolkit::ControlRenderer&, const Vector4& ) + * @copydoc Toolkit::RendererFactory::ResetRenderer( Toolkit::ControlRenderer&, Actor& actor, const Vector4& ) */ - bool ResetRenderer( Toolkit::ControlRenderer& renderer, const Vector4& color ); + void ResetRenderer( Toolkit::ControlRenderer& renderer, Actor& actor, const Vector4& color ); /** * @copydoc Toolkit::RenderFactory::GetControlRenderer( float, const Vector4& ) @@ -80,9 +80,9 @@ public: Toolkit::ControlRenderer GetControlRenderer( const Image& image ); /** - * @copydoc Toolkit::RendererFactory::ResetRenderer( Toolkit::ControlRenderer&, const Image& ) + * @copydoc Toolkit::RendererFactory::ResetRenderer( Toolkit::ControlRenderer&, Actor& actor, const Image& ) */ - bool ResetRenderer( Toolkit::ControlRenderer& renderer, const Image& image ); + void ResetRenderer( Toolkit::ControlRenderer& renderer, Actor& actor, const Image& image ); /** * @copydoc Toolkit::RenderFactory::GetControlRenderer( const std::string& ) @@ -90,9 +90,9 @@ public: Toolkit::ControlRenderer GetControlRenderer( const std::string& image ); /** - * @copydoc Toolkit::RendererFactory::ResetRenderer( Toolkit::ControlRenderer&, const std::string& ) + * @copydoc Toolkit::RendererFactory::ResetRenderer( Toolkit::ControlRenderer&, Actor& actor, const std::string& ) */ - bool ResetRenderer( Toolkit::ControlRenderer& renderer, const std::string& image ); + void ResetRenderer( Toolkit::ControlRenderer& renderer, Actor& actor, const std::string& image ); public: /** diff --git a/dali-toolkit/public-api/controls/control-impl.cpp b/dali-toolkit/public-api/controls/control-impl.cpp index c3ca785..429648b 100644 --- a/dali-toolkit/public-api/controls/control-impl.cpp +++ b/dali-toolkit/public-api/controls/control-impl.cpp @@ -406,24 +406,17 @@ void Control::SetBackgroundColor( const Vector4& color ) if( mImpl->mBackgroundRenderer ) { - Toolkit::ControlRenderer currentRenderer( mImpl->mBackgroundRenderer ); - // if ResetRenderer returns false, we continue to use the current renderer with a new color set to it. - if( ! factory.ResetRenderer( mImpl->mBackgroundRenderer, color ) ) - { - return; - } - // ResetRenderer returns true, a new renderer is created. Remove the current renderer and reset. - currentRenderer.RemoveAndReset( self ); + factory.ResetRenderer( mImpl->mBackgroundRenderer, self, color ); } else { mImpl->mBackgroundRenderer = factory.GetControlRenderer( color ); - } - if( self.OnStage() ) - { - mImpl->mBackgroundRenderer.SetDepthIndex( BACKGROUND_DEPTH_INDEX ); - mImpl->mBackgroundRenderer.SetOnStage( self ); + if( self.OnStage() ) + { + mImpl->mBackgroundRenderer.SetDepthIndex( BACKGROUND_DEPTH_INDEX ); + mImpl->mBackgroundRenderer.SetOnStage( self ); + } } } @@ -463,30 +456,23 @@ void Control::SetBackgroundImage( Image image ) if( mImpl->mBackgroundRenderer ) { - Toolkit::ControlRenderer currentRenderer( mImpl->mBackgroundRenderer ); - // if ResetRenderer returns false, we continue to use the current renderer with a new image set to it. - if( ! factory.ResetRenderer( mImpl->mBackgroundRenderer, image ) ) - { - return; - } - // ResetRenderer returns true, a new renderer is created. Remove the current renderer and reset. - currentRenderer.RemoveAndReset( self ); + factory.ResetRenderer( mImpl->mBackgroundRenderer, self, image ); } else { mImpl->mBackgroundRenderer = factory.GetControlRenderer( image ); - } - if( self.OnStage() ) - { - mImpl->mBackgroundRenderer.SetDepthIndex( BACKGROUND_DEPTH_INDEX ); - mImpl->mBackgroundRenderer.SetOnStage( self ); + if( self.OnStage() ) + { + mImpl->mBackgroundRenderer.SetDepthIndex( BACKGROUND_DEPTH_INDEX ); + mImpl->mBackgroundRenderer.SetOnStage( self ); + } } } void Control::ClearBackground() { - Actor self(Self()); + Actor self( Self() ); mImpl->mBackgroundRenderer.RemoveAndReset( self ); }