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=f142d59a70f84ca3479d119bb442a9acab2ae9a8;hp=477096035d44ab9976ba7d661e2280fd3db11f64;hb=2c97b9f743493b56e6256fbce8ef5c3e2080572c;hpb=4c1f4bfb9eb5b956b64a6c9bf077217fc0ca9234 diff --git a/dali-toolkit/internal/controls/renderers/image/image-renderer.cpp b/dali-toolkit/internal/controls/renderers/image/image-renderer.cpp index 4770960..f142d59 100644 --- a/dali-toolkit/internal/controls/renderers/image/image-renderer.cpp +++ b/dali-toolkit/internal/controls/renderers/image/image-renderer.cpp @@ -27,6 +27,7 @@ #include #include #include +#include namespace Dali { @@ -39,39 +40,42 @@ namespace Internal namespace { -const char * const RENDERER_TYPE("renderer-type"); -const char * const RENDERER_TYPE_VALUE("image-renderer"); +const char * const RENDERER_TYPE("rendererType"); +const char * const RENDERER_TYPE_VALUE("imageRenderer"); // property names -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" ); +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("shrink-to-fit"); -const char * const SCALE_TO_FILL("scale-to-fill"); -const char * const FIT_WIDTH("fit-width"); -const char * const FIT_HEIGHT("fit-height"); +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("box-then-nearest"); -const char * const BOX_THEN_LINEAR("box-then-linear"); -const char * const NO_FILTER("no-filter"); -const char * const DONT_CARE("dont-care"); +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"); -std::string TEXTURE_UNIFORM_NAME = "sTexture"; +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 @@ -79,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 ); @@ -95,17 +99,6 @@ const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER( }\n ); -void AddQuadIndices( Vector< unsigned int >& indices, unsigned int rowIdx, unsigned int nextRowIdx ) -{ - indices.PushBack( rowIdx ); - indices.PushBack( nextRowIdx + 1 ); - indices.PushBack( rowIdx + 1 ); - - indices.PushBack( rowIdx ); - indices.PushBack( nextRowIdx ); - indices.PushBack( nextRowIdx + 1 ); -} - Geometry GenerateGeometry( const Vector< Vector2 >& vertices, const Vector< unsigned int >& indices ) { Property::Map vertexFormat; @@ -128,6 +121,7 @@ Geometry GenerateGeometry( const Vector< Vector2 >& vertices, const Vector< unsi Geometry geometry = Geometry::New(); geometry.AddVertexBuffer( vertexPropertyBuffer ); geometry.SetIndexBuffer( indexPropertyBuffer ); + geometry.SetGeometryType( Geometry::TRIANGLE_STRIP ); return geometry; } @@ -164,15 +158,27 @@ Geometry CreateGeometry( RendererFactoryCache& factoryCache, ImageDimensions gri // Create indices Vector< unsigned int > indices; - indices.Reserve( gridWidth * gridHeight * 6 ); + indices.Reserve( (gridWidth+2)*gridHeight*2 - 2); - unsigned int rowIdx = 0; - unsigned int nextRowIdx = gridWidth + 1; - for( int y = 0; y < gridHeight; ++y, ++nextRowIdx, ++rowIdx ) + for( unsigned int row = 0u; row < gridHeight; ++row ) { - for( int x = 0; x < gridWidth; ++x, ++nextRowIdx, ++rowIdx ) + 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 { - AddQuadIndices( indices, rowIdx, nextRowIdx ); + indices.PushBack( nextRowStartIndex + gridWidth ); } } @@ -184,8 +190,10 @@ Geometry CreateGeometry( RendererFactoryCache& factoryCache, ImageDimensions gri } //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 ) @@ -196,9 +204,9 @@ ImageRenderer::~ImageRenderer() { } -void ImageRenderer::DoInitialize( 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 ) @@ -303,6 +311,37 @@ void ImageRenderer::DoInitialize( RendererFactoryCache& factoryCache, const Prop mDesiredSize = ImageDimensions( desiredWidth, desiredHeight ); } + + 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 ) @@ -344,14 +383,127 @@ void ImageRenderer::SetOffset( const Vector2& 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() ) { - mImage = Dali::ResourceImage::New( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode ); + 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(); + // Set value to the uTextureRect uniform + SetTextureRectUniform( FULL_TEXTURE_RECT ); + } + + ApplyImageToSampler( image ); + } } void ImageRenderer::DoSetOffStage( Actor& actor ) @@ -359,8 +511,16 @@ 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::DoCreatePropertyMap( Property::Map& map ) const @@ -459,121 +619,155 @@ void ImageRenderer::DoCreatePropertyMap( Property::Map& map ) const } } -void ImageRenderer::Initialize( RendererFactoryCache& factoryCache ) +Shader ImageRenderer::GetImageShader( RendererFactoryCache& factoryCache ) { - if( !mImpl->mCustomShader ) + Shader shader = factoryCache.GetShader( RendererFactoryCache::IMAGE_SHADER ); + if( !shader ) { - mImpl->mGeometry = CreateGeometry( factoryCache, ImageDimensions( 1, 1 ) ); + shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ); + factoryCache.SaveShader( RendererFactoryCache::IMAGE_SHADER, shader ); + } + return shader; +} - mImpl->mShader = factoryCache.GetShader( RendererFactoryCache::IMAGE_SHADER ); +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( !mImpl->mShader ) - { - mImpl->mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ); - factoryCache.SaveShader( RendererFactoryCache::IMAGE_SHADER, mImpl->mShader ); - } - } - else + if( mImageUrl != imageUrl ) { - mImpl->mGeometry = CreateGeometry( factoryCache, mImpl->mCustomShader->mGridSize ); - - if( mImpl->mCustomShader->mVertexShader.empty() && mImpl->mCustomShader->mFragmentShader.empty() ) + if( mImpl->mRenderer ) { - mImpl->mShader = factoryCache.GetShader( RendererFactoryCache::IMAGE_SHADER ); + if( GetIsFromCache() ) + { + //remove old renderer + if( actor ) + { + actor.RemoveRenderer( mImpl->mRenderer ); + } - if( !mImpl->mShader ) + //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 { - mImpl->mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ); - factoryCache.SaveShader( RendererFactoryCache::IMAGE_SHADER, mImpl->mShader ); + ResourceImage image = Dali::ResourceImage::New( imageUrl, mDesiredSize, mFittingMode, mSamplingMode ); + image.LoadingFinishedSignal().Connect( this, &ImageRenderer::OnImageLoaded ); + ApplyImageToSampler( image ); } } - 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 ); - } + + mImageUrl = imageUrl; + + mImage.Reset(); } +} - if( mImpl->mRenderer ) +void ImageRenderer::SetImage( Actor& actor, const Image& image ) +{ + if( mImage != image ) { - mImpl->mRenderer.SetGeometry( mImpl->mGeometry ); - Material material = mImpl->mRenderer.GetMaterial(); - if( material ) + if( mImpl->mRenderer ) { - material.SetShader( mImpl->mShader ); + 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 ); -void ImageRenderer::SetImage( const std::string& imageUrl ) -{ - SetImage( imageUrl, 0, 0, Dali::FittingMode::DEFAULT, Dali::SamplingMode::DEFAULT ); + mImage = image; + mImageUrl.clear(); + mDesiredSize = ImageDimensions(); + mFittingMode = FittingMode::DEFAULT; + mSamplingMode = SamplingMode::DEFAULT; + } } -void ImageRenderer::SetImage( const std::string& imageUrl, int desiredWidth, int desiredHeight, Dali::FittingMode::Type fittingMode, Dali::SamplingMode::Type samplingMode ) +void ImageRenderer::ApplyImageToSampler( const Image& image ) { - if( mImageUrl != imageUrl ) + if( image ) { - 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 + Material material = mImpl->mRenderer.GetMaterial(); + if( material ) { - mImage.Reset(); + int index = material.GetTextureIndex( TEXTURE_UNIFORM_NAME ); + if( index != -1 ) + { + material.SetTextureImage( index, image ); + return; + } + + material.AddTexture( image, TEXTURE_UNIFORM_NAME ); } } } -void ImageRenderer::SetImage( Image image ) +void ImageRenderer::OnImageLoaded( ResourceImage image ) { - if( mImage != image ) + if( image.GetLoadingState() == Dali::ResourceLoadingFailed ) { - mImageUrl.clear(); - mDesiredSize = ImageDimensions(); - mFittingMode = FittingMode::DEFAULT; - mSamplingMode = SamplingMode::DEFAULT; - mImage = image; - - if( mImage && mImpl->mIsOnStage ) + Image brokenImage = RendererFactory::GetBrokenRendererImage(); + if( mImpl->mRenderer ) { - ApplyImageToSampler(); + ApplyImageToSampler( brokenImage ); } } } -Image ImageRenderer::GetImage() const +void ImageRenderer::SetTextureRectUniform( const Vector4& textureRect ) { - return mImage; + if( mImpl->mRenderer ) + { + // Register/Set property. + mImpl->mRenderer.RegisterProperty( TEXTURE_RECT_UNIFORM_NAME, textureRect ); + } } -void ImageRenderer::ApplyImageToSampler() +void ImageRenderer::CleanCache(const std::string& url) { - if( mImage ) + Material material = mImpl->mRenderer.GetMaterial(); + mImpl->mRenderer.Reset(); + if( mFactoryCache.CleanRendererCache( url ) ) { - Material material = mImpl->mRenderer.GetMaterial(); - if( material ) - { - 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 ); - } + mAtlasManager.Remove( material, mTextureRect ); } }