X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fcontrols%2Frenderers%2Fimage%2Fimage-renderer.cpp;h=27c6af5c908b277934668ce4a8002f436f5d6b45;hp=50fa5b8a6c2f187ceb878666bd88eddcfe5df37b;hb=af4073fd7a4f946e26110ecd608ef8e748c078aa;hpb=618c084142032296c60a188b9438d63a81a2d264 diff --git a/dali-toolkit/internal/controls/renderers/image/image-renderer.cpp b/dali-toolkit/internal/controls/renderers/image/image-renderer.cpp index 50fa5b8..27c6af5 100644 --- a/dali-toolkit/internal/controls/renderers/image/image-renderer.cpp +++ b/dali-toolkit/internal/controls/renderers/image/image-renderer.cpp @@ -18,11 +18,16 @@ // CLASS HEADER #include "image-renderer.h" +// EXTERNAL HEADER +#include +#include + +// INTERNAL HEADER #include #include #include #include -#include +#include namespace Dali { @@ -35,20 +40,42 @@ namespace Internal namespace { - -const char * const IMAGE_URL_NAME("image-url"); -const char * const IMAGE_FITTING_MODE("image-fitting-mode"); -const char * const IMAGE_SAMPLING_MODE("image-sampling-mode"); -const char * const IMAGE_DESIRED_WIDTH("image-desired-width"); -const char * const IMAGE_DESIRED_HEIGHT("image-desired-height"); - -std::string TEXTURE_UNIFORM_NAME = "sTexture"; +const char * const RENDERER_TYPE("rendererType"); +const char * const RENDERER_TYPE_VALUE("imageRenderer"); + +// property names +const char * const IMAGE_URL_NAME( "imageUrl" ); +const char * const IMAGE_FITTING_MODE( "imageFittingMode" ); +const char * const IMAGE_SAMPLING_MODE( "imageSamplingMode" ); +const char * const IMAGE_DESIRED_WIDTH( "imageDesiredWidth" ); +const char * const IMAGE_DESIRED_HEIGHT( "imageDesiredHeight" ); + +// fitting modes +const char * const SHRINK_TO_FIT("shrinkToFit"); +const char * const SCALE_TO_FILL("scaleToFill"); +const char * const FIT_WIDTH("fitWidth"); +const char * const FIT_HEIGHT("fitHeight"); +const char * const DEFAULT("default"); + +// sampling modes +const char * const BOX("box"); +const char * const NEAREST("nearest"); +const char * const LINEAR("linear"); +const char * const BOX_THEN_NEAREST("boxThenNearest"); +const char * const BOX_THEN_LINEAR("boxThenLinear"); +const char * const NO_FILTER("noFilter"); +const char * const DONT_CARE("dontCare"); + +const std::string TEXTURE_UNIFORM_NAME = "sTexture"; +const std::string TEXTURE_RECT_UNIFORM_NAME = "uTextureRect"; +const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f); const char* VERTEX_SHADER = DALI_COMPOSE_SHADER( attribute mediump vec2 aPosition;\n varying mediump vec2 vTexCoord;\n uniform mediump mat4 uMvpMatrix;\n uniform mediump vec3 uSize;\n + uniform mediump vec4 uTextureRect;\n \n void main()\n {\n @@ -56,7 +83,7 @@ const char* VERTEX_SHADER = DALI_COMPOSE_SHADER( vertexPosition.xyz *= uSize;\n vertexPosition = uMvpMatrix * vertexPosition;\n \n - vTexCoord = aPosition + vec2(0.5);\n + vTexCoord = mix( uTextureRect.xy, uTextureRect.zw, aPosition + vec2(0.5));\n gl_Position = vertexPosition;\n }\n ); @@ -72,10 +99,101 @@ const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER( }\n ); +Geometry GenerateGeometry( const Vector< Vector2 >& vertices, const Vector< unsigned int >& indices ) +{ + Property::Map vertexFormat; + vertexFormat[ "aPosition" ] = Property::VECTOR2; + PropertyBuffer vertexPropertyBuffer = PropertyBuffer::New( vertexFormat, vertices.Size() ); + if( vertices.Size() > 0 ) + { + vertexPropertyBuffer.SetData( &vertices[ 0 ] ); + } + + Property::Map indexFormat; + indexFormat[ "indices" ] = Property::INTEGER; + PropertyBuffer indexPropertyBuffer = PropertyBuffer::New( indexFormat, indices.Size() ); + if( indices.Size() > 0 ) + { + indexPropertyBuffer.SetData( &indices[ 0 ] ); + } + + // Create the geometry object + Geometry geometry = Geometry::New(); + geometry.AddVertexBuffer( vertexPropertyBuffer ); + geometry.SetIndexBuffer( indexPropertyBuffer ); + geometry.SetGeometryType( Geometry::TRIANGLE_STRIP ); + + return geometry; +} + +Geometry CreateGeometry( RendererFactoryCache& factoryCache, ImageDimensions gridSize ) +{ + Geometry geometry; + + if( gridSize == ImageDimensions( 1, 1 ) ) + { + geometry = factoryCache.GetGeometry( RendererFactoryCache::QUAD_GEOMETRY ); + if( !geometry ) + { + geometry = factoryCache.CreateQuadGeometry(); + factoryCache.SaveGeometry( RendererFactoryCache::QUAD_GEOMETRY, geometry ); + } + } + else + { + uint16_t gridWidth = gridSize.GetWidth(); + uint16_t gridHeight = gridSize.GetHeight(); + + // Create vertices + Vector< Vector2 > vertices; + vertices.Reserve( ( gridWidth + 1 ) * ( gridHeight + 1 ) ); + + for( int y = 0; y < gridHeight + 1; ++y ) + { + for( int x = 0; x < gridWidth + 1; ++x ) + { + vertices.PushBack( Vector2( (float)x/gridWidth - 0.5f, (float)y/gridHeight - 0.5f) ); + } + } + + // Create indices + Vector< unsigned int > indices; + indices.Reserve( (gridWidth+2)*gridHeight*2 - 2); + + for( unsigned int row = 0u; row < gridHeight; ++row ) + { + unsigned int rowStartIndex = row*(gridWidth+1u); + unsigned int nextRowStartIndex = rowStartIndex + gridWidth +1u; + + if( row != 0u ) // degenerate index on non-first row + { + indices.PushBack( rowStartIndex ); + } + + for( unsigned int column = 0u; column < gridWidth+1u; column++) // main strip + { + indices.PushBack( rowStartIndex + column); + indices.PushBack( nextRowStartIndex + column); + } + + if( row != gridHeight-1u ) // degenerate index on non-last row + { + indices.PushBack( nextRowStartIndex + gridWidth ); + } + } + + return GenerateGeometry( vertices, indices ); + } + + return geometry; +} + } //unnamed namespace -ImageRenderer::ImageRenderer() -: ControlRenderer(), +ImageRenderer::ImageRenderer( RendererFactoryCache& factoryCache, ImageAtlasManager& atlasManager ) +: ControlRenderer( factoryCache ), + mAtlasManager( atlasManager ), + mTextureRect( FULL_TEXTURE_RECT ), mDesiredSize(), mFittingMode( FittingMode::DEFAULT ), mSamplingMode( SamplingMode::DEFAULT ) @@ -86,14 +204,18 @@ ImageRenderer::~ImageRenderer() { } -void ImageRenderer::Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap ) +void ImageRenderer::DoInitialize( Actor& actor, const Property::Map& propertyMap ) { - Initialize(factoryCache); + std::string oldImageUrl = mImageUrl; Property::Value* imageURLValue = propertyMap.Find( IMAGE_URL_NAME ); if( imageURLValue ) { imageURLValue->Get( mImageUrl ); + if( !mImageUrl.empty() ) + { + mImage.Reset(); + } Property::Value* fittingValue = propertyMap.Find( IMAGE_FITTING_MODE ); if( fittingValue ) @@ -102,23 +224,23 @@ void ImageRenderer::Initialize( RendererFactoryCache& factoryCache, const Proper fittingValue->Get( fitting ); mFittingMode = FittingMode::DEFAULT; - if( fitting == "shrink-to-fit" ) + if( fitting == SHRINK_TO_FIT ) { mFittingMode = FittingMode::SHRINK_TO_FIT; } - else if( fitting == "scale-to-fill" ) + else if( fitting == SCALE_TO_FILL ) { mFittingMode = FittingMode::SCALE_TO_FILL; } - else if( fitting == "fit-width" ) + else if( fitting == FIT_WIDTH ) { mFittingMode = FittingMode::FIT_WIDTH; } - else if( fitting == "fit-height" ) + else if( fitting == FIT_HEIGHT ) { mFittingMode = FittingMode::FIT_HEIGHT; } - else if( fitting == "default" ) + else if( fitting == DEFAULT ) { mFittingMode = FittingMode::DEFAULT; } @@ -135,35 +257,35 @@ void ImageRenderer::Initialize( RendererFactoryCache& factoryCache, const Proper samplingValue->Get( sampling ); mSamplingMode = SamplingMode::DEFAULT; - if( sampling == "box" ) + if( sampling == BOX ) { mSamplingMode = SamplingMode::BOX; } - else if( sampling == "nearest" ) + else if( sampling == NEAREST ) { mSamplingMode = SamplingMode::NEAREST; } - else if( sampling == "linear" ) + else if( sampling == LINEAR ) { mSamplingMode = SamplingMode::LINEAR; } - else if( sampling == "box-then-nearest" ) + else if( sampling == BOX_THEN_NEAREST ) { mSamplingMode = SamplingMode::BOX_THEN_NEAREST; } - else if( sampling == "box-then-linear" ) + else if( sampling == BOX_THEN_LINEAR ) { mSamplingMode = SamplingMode::BOX_THEN_LINEAR; } - else if( sampling == "no-filter" ) + else if( sampling == NO_FILTER ) { mSamplingMode = SamplingMode::NO_FILTER; } - else if( sampling == "dont-care" ) + else if( sampling == DONT_CARE ) { mSamplingMode = SamplingMode::DONT_CARE; } - else if( sampling == "default" ) + else if( sampling == DEFAULT ) { mSamplingMode = SamplingMode::DEFAULT; } @@ -190,34 +312,198 @@ void ImageRenderer::Initialize( RendererFactoryCache& factoryCache, const Proper mDesiredSize = ImageDimensions( desiredWidth, desiredHeight ); } - mImage.Reset(); + if( mImpl->mRenderer ) + { + //remove old renderer + if( actor ) + { + actor.RemoveRenderer( mImpl->mRenderer ); + } + + //clean the cache + if( !oldImageUrl.empty() ) + { + CleanCache( 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 ) { ControlRenderer::SetSize( size ); - // ToDo: renderer responds to the size change +} + +void ImageRenderer::GetNaturalSize( Vector2& naturalSize ) const +{ + if(mImage) + { + naturalSize.x = mImage.GetWidth(); + naturalSize.y = mImage.GetHeight(); + return; + } + else if( mDesiredSize.GetWidth()>0 && mDesiredSize.GetHeight()>0) + { + naturalSize.x = mDesiredSize.GetWidth(); + naturalSize.y = mDesiredSize.GetHeight(); + return; + } + else if( !mImageUrl.empty() ) + { + ImageDimensions dimentions = ResourceImage::GetImageSize( mImageUrl ); + naturalSize.x = dimentions.GetWidth(); + naturalSize.y = dimentions.GetHeight(); + return; + } + + naturalSize = Vector2::ZERO; } void ImageRenderer::SetClipRect( const Rect& clipRect ) { ControlRenderer::SetClipRect( clipRect ); - //ToDo: renderer responds to the clipRect change } void ImageRenderer::SetOffset( const Vector2& offset ) { - //ToDo: renderer applies the offset } +Renderer ImageRenderer::CreateRenderer() const +{ + Geometry geometry; + Shader shader; + + if( !mImpl->mCustomShader ) + { + geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) ); + shader = GetImageShader(mFactoryCache); + } + else + { + geometry = CreateGeometry( mFactoryCache, mImpl->mCustomShader->mGridSize ); + if( mImpl->mCustomShader->mVertexShader.empty() && mImpl->mCustomShader->mFragmentShader.empty() ) + { + shader = GetImageShader(mFactoryCache); + } + 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 ); + } + } + + Material material = Material::New( shader ); + return Renderer::New( geometry, material ); +} + +void ImageRenderer::InitializeRenderer( const std::string& imageUrl ) +{ + if( mImageUrl.empty() ) + { + mImpl->mFlags &= ~Impl::IS_FROM_CACHE; + return; + } + + mImpl->mRenderer.Reset(); + if( !mImpl->mCustomShader ) + { + mImpl->mRenderer = mFactoryCache.GetRenderer( imageUrl ); + if( !mImpl->mRenderer ) + { + Material material = mAtlasManager.Add(mTextureRect, imageUrl, mDesiredSize, mFittingMode, mSamplingMode ); + if( material ) + { + Geometry geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) ); + mImpl->mRenderer = Renderer::New( geometry, material ); + SetTextureRectUniform(mTextureRect); + } + else // big image, atlasing is not applied + { + mImpl->mRenderer = CreateRenderer(); + SetTextureRectUniform(FULL_TEXTURE_RECT); + + 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 ); + } + else + { + Property::Value textureRect = mImpl->mRenderer.GetProperty( mImpl->mRenderer.GetPropertyIndex(TEXTURE_RECT_UNIFORM_NAME) ); + textureRect.Get( mTextureRect ); + } + 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::InitializeRenderer( const Image& image ) +{ + mImpl->mFlags &= ~Impl::IS_FROM_CACHE; + + if( !image ) + { + return; + } + + mImpl->mRenderer = CreateRenderer(); + ApplyImageToSampler( image ); + SetTextureRectUniform( FULL_TEXTURE_RECT ); +} + + void ImageRenderer::DoSetOnStage( Actor& actor ) { - if( !mImageUrl.empty() && !mImage ) + if( !mImageUrl.empty() ) + { + InitializeRenderer( mImageUrl ); + } + else if( mImage ) { - mImage = Dali::ResourceImage::New( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode ); + InitializeRenderer( mImage ); } - ApplyImageToSampler(); + 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; + + // Set value to the uTextureRect uniform + SetTextureRectUniform( FULL_TEXTURE_RECT ); + } + + ApplyImageToSampler( image ); + } } void ImageRenderer::DoSetOffStage( Actor& actor ) @@ -225,103 +511,273 @@ void ImageRenderer::DoSetOffStage( Actor& actor ) //If we own the image then make sure we release it when we go off stage if( !mImageUrl.empty() ) { + actor.RemoveRenderer( mImpl->mRenderer ); + CleanCache(mImageUrl); + mImage.Reset(); } + else + { + actor.RemoveRenderer( mImpl->mRenderer ); + mImpl->mRenderer.Reset(); + } } -void ImageRenderer::Initialize( RendererFactoryCache& factoryCache ) +void ImageRenderer::DoCreatePropertyMap( Property::Map& map ) const { - mImpl->mGeometry = factoryCache.GetGeometry( RendererFactoryCache::QUAD_GEOMETRY ); - if( !(mImpl->mGeometry) ) + map.Clear(); + map.Insert( RENDERER_TYPE, RENDERER_TYPE_VALUE ); + if( !mImageUrl.empty() ) { - mImpl->mGeometry = factoryCache.CreateQuadGeometry(); - factoryCache.SaveGeometry( RendererFactoryCache::QUAD_GEOMETRY, mImpl->mGeometry ); + map.Insert( IMAGE_URL_NAME, mImageUrl ); + map.Insert( IMAGE_DESIRED_WIDTH, mDesiredSize.GetWidth() ); + map.Insert( IMAGE_DESIRED_HEIGHT, mDesiredSize.GetHeight() ); + } + else if( mImage ) + { + map.Insert( IMAGE_DESIRED_WIDTH, static_cast(mImage.GetWidth()) ); + map.Insert( IMAGE_DESIRED_HEIGHT, static_cast(mImage.GetHeight()) ); + + ResourceImage resourceImage = ResourceImage::DownCast(mImage); + if( resourceImage ) + { + map.Insert( IMAGE_URL_NAME, resourceImage.GetUrl() ); + } } - mImpl->mShader = factoryCache.GetShader( RendererFactoryCache::IMAGE_SHADER ); - if( !mImpl->mShader ) + switch( mFittingMode ) { - mImpl->mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ); - factoryCache.SaveShader( RendererFactoryCache::IMAGE_SHADER, mImpl->mShader ); + case Dali::FittingMode::FIT_HEIGHT: + { + map.Insert( IMAGE_FITTING_MODE, FIT_HEIGHT ); + break; + } + case Dali::FittingMode::FIT_WIDTH: + { + map.Insert( IMAGE_FITTING_MODE, FIT_WIDTH ); + break; + } + case Dali::FittingMode::SCALE_TO_FILL: + { + map.Insert( IMAGE_FITTING_MODE, SCALE_TO_FILL ); + break; + } + case Dali::FittingMode::SHRINK_TO_FIT: + { + map.Insert( IMAGE_FITTING_MODE, SHRINK_TO_FIT ); + break; + } + default: + { + map.Insert( IMAGE_FITTING_MODE, DEFAULT ); + break; + } } - mDesiredSize = ImageDimensions(); - mFittingMode = FittingMode::DEFAULT; - mSamplingMode = SamplingMode::DEFAULT; - mImageUrl.clear(); + switch( mSamplingMode ) + { + case Dali::SamplingMode::BOX: + { + map.Insert( IMAGE_SAMPLING_MODE, BOX ); + break; + } + case Dali::SamplingMode::NEAREST: + { + map.Insert( IMAGE_SAMPLING_MODE, NEAREST ); + break; + } + case Dali::SamplingMode::LINEAR: + { + map.Insert( IMAGE_SAMPLING_MODE, LINEAR ); + break; + } + case Dali::SamplingMode::BOX_THEN_LINEAR: + { + map.Insert( IMAGE_SAMPLING_MODE, BOX_THEN_LINEAR ); + break; + } + case Dali::SamplingMode::BOX_THEN_NEAREST: + { + map.Insert( IMAGE_SAMPLING_MODE, BOX_THEN_NEAREST ); + break; + } + case Dali::SamplingMode::NO_FILTER: + { + map.Insert( IMAGE_SAMPLING_MODE, NO_FILTER ); + break; + } + case Dali::SamplingMode::DONT_CARE: + { + map.Insert( IMAGE_SAMPLING_MODE, DONT_CARE ); + break; + } + default: + { + map.Insert( IMAGE_SAMPLING_MODE, DEFAULT ); + break; + } + } } -void ImageRenderer::SetImage( const std::string& imageUrl ) +Shader ImageRenderer::GetImageShader( RendererFactoryCache& factoryCache ) { - SetImage( imageUrl, 0, 0, Dali::FittingMode::DEFAULT, Dali::SamplingMode::DEFAULT ); + Shader shader = factoryCache.GetShader( RendererFactoryCache::IMAGE_SHADER ); + if( !shader ) + { + shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ); + factoryCache.SaveShader( RendererFactoryCache::IMAGE_SHADER, shader ); + } + return shader; } -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, ImageDimensions size, Dali::FittingMode::Type fittingMode, Dali::SamplingMode::Type samplingMode ) { + mDesiredSize = size; + mFittingMode = fittingMode; + mSamplingMode = samplingMode; + if( mImageUrl != imageUrl ) { - mImageUrl = imageUrl; - mDesiredSize = ImageDimensions( desiredWidth, desiredHeight ); - mFittingMode = fittingMode; - mSamplingMode = samplingMode; - - if( !mImageUrl.empty() && mImpl->mIsOnStage ) - { - mImage = Dali::ResourceImage::New( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode ); - ApplyImageToSampler(); - } - else + if( mImpl->mRenderer ) { - mImage.Reset(); + if( GetIsFromCache() ) + { + //remove old renderer + if( actor ) + { + actor.RemoveRenderer( mImpl->mRenderer ); + } + + //clean the cache + if( !mImageUrl.empty() ) + { + CleanCache(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; + + 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() ) + { + CleanCache(mImageUrl); + } + + //Initialize the renderer + InitializeRenderer( image ); + + //add the new renderer to the actor + if( actor && mImpl->mRenderer ) + { + actor.AddRenderer( mImpl->mRenderer ); + } + } + else + { + ApplyImageToSampler( image ); + } + } + SetTextureRectUniform( FULL_TEXTURE_RECT ); + + mImage = image; mImageUrl.clear(); mDesiredSize = ImageDimensions(); mFittingMode = FittingMode::DEFAULT; mSamplingMode = SamplingMode::DEFAULT; - mImage = image; + } +} - if( mImage && mImpl->mIsOnStage ) +void ImageRenderer::ApplyImageToSampler( const Image& image ) +{ + if( image ) + { + Material material = mImpl->mRenderer.GetMaterial(); + if( material ) { - ApplyImageToSampler(); + int index = material.GetTextureIndex( TEXTURE_UNIFORM_NAME ); + if( index != -1 ) + { + material.SetTextureImage( index, image ); + return; + } + + material.AddTexture( image, TEXTURE_UNIFORM_NAME ); } } } -Image ImageRenderer::GetImage() const +void ImageRenderer::OnImageLoaded( ResourceImage image ) { - return mImage; + if( image.GetLoadingState() == Dali::ResourceLoadingFailed ) + { + Image brokenImage = RendererFactory::GetBrokenRendererImage(); + if( mImpl->mRenderer ) + { + ApplyImageToSampler( brokenImage ); + } + } } -void ImageRenderer::ApplyImageToSampler() +void ImageRenderer::SetTextureRectUniform( const Vector4& textureRect ) { - if( mImage ) + if( mImpl->mRenderer ) { - Material material = mImpl->mRenderer.GetMaterial(); - if( material ) + Property::Index index = mImpl->mRenderer.GetPropertyIndex( TEXTURE_RECT_UNIFORM_NAME ); + if( index == Property::INVALID_INDEX ) { - for( std::size_t i = 0; i < material.GetNumberOfSamplers(); ++i ) - { - Sampler sampler = material.GetSamplerAt( i ); - if( sampler.GetUniformName() == TEXTURE_UNIFORM_NAME ) - { - sampler.SetImage( mImage ); - return; - } - } - - Sampler sampler = Sampler::New( mImage, TEXTURE_UNIFORM_NAME ); - material.AddSampler( sampler ); + index = mImpl->mRenderer.RegisterProperty( TEXTURE_RECT_UNIFORM_NAME, textureRect ); + } + else + { + mImpl->mRenderer.SetProperty( index, textureRect ); } } } +void ImageRenderer::CleanCache(const std::string& url) +{ + Material material = mImpl->mRenderer.GetMaterial(); + mImpl->mRenderer.Reset(); + if( mFactoryCache.CleanRendererCache( url ) ) + { + mAtlasManager.Remove( material, mTextureRect ); + } +} + } // namespace Internal } // namespace Toolkit