X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fvisuals%2Fimage%2Fimage-visual.cpp;h=a0197cd6afcca4dca1377b944333d1b6e9beb2bc;hp=cbfa4457d5dcebe30d3a89c7fb1f9ff9b6ad7bed;hb=0a98cc9159a2b5868987ec7f0b31b76f3dc10259;hpb=a1e6ba9ce55ab38ec56cbd718cb62624a8c656a3 diff --git a/dali-toolkit/internal/visuals/image/image-visual.cpp b/dali-toolkit/internal/visuals/image/image-visual.cpp index cbfa445..a0197cd 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.cpp +++ b/dali-toolkit/internal/visuals/image/image-visual.cpp @@ -22,7 +22,6 @@ #include // for strncasecmp #include #include -#include #include #include #include @@ -31,7 +30,7 @@ // INTERNAL HEADER #include -#include +#include #include #include #include @@ -58,10 +57,7 @@ const char * const IMAGE_FITTING_MODE( "fittingMode" ); const char * const IMAGE_SAMPLING_MODE( "samplingMode" ); const char * const IMAGE_DESIRED_WIDTH( "desiredWidth" ); const char * const IMAGE_DESIRED_HEIGHT( "desiredHeight" ); -const char * const IMAGE_WRAP_MODE_U("wrapModeU"); -const char * const IMAGE_WRAP_MODE_V("wrapModeV"); const char * const SYNCHRONOUS_LOADING( "synchronousLoading" ); -const char * const BATCHING_ENABLED( "batchingEnabled" ); // fitting modes DALI_ENUM_TO_STRING_TABLE_BEGIN( FITTING_MODE ) @@ -91,9 +87,6 @@ DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::WrapMode, REPEAT ) DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::WrapMode, MIRRORED_REPEAT ) DALI_ENUM_TO_STRING_TABLE_END( WRAP_MODE ) -const std::string PIXEL_AREA_UNIFORM_NAME = "pixelArea"; -const std::string WRAP_MODE_UNIFORM_NAME = "wrapMode"; - const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f); const char* DEFAULT_SAMPLER_TYPENAME = "sampler2D"; @@ -105,12 +98,24 @@ const char* VERTEX_SHADER = DALI_COMPOSE_SHADER( uniform mediump vec4 pixelArea; varying mediump vec2 vTexCoord;\n \n + + //Visual size and offset + uniform mediump vec2 offset;\n + uniform mediump vec2 size;\n + uniform mediump vec4 offsetSizeMode;\n + uniform mediump vec2 origin;\n + uniform mediump vec2 anchorPoint;\n + + vec4 ComputeVertexPosition()\n + {\n + vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw );\n + vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);\n + return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );\n + }\n + void main()\n {\n - mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n - vertexPosition.xyz *= uSize;\n - vertexPosition = uMvpMatrix * vertexPosition;\n - \n + mediump vec4 vertexPosition = uMvpMatrix * ComputeVertexPosition();\n vTexCoord = pixelArea.xy+pixelArea.zw*(aPosition + vec2(0.5) );\n gl_Position = vertexPosition;\n }\n @@ -120,10 +125,16 @@ const char* FRAGMENT_SHADER_NO_ATLAS = DALI_COMPOSE_SHADER( varying mediump vec2 vTexCoord;\n uniform sampler2D sTexture;\n uniform lowp vec4 uColor;\n + uniform lowp vec4 mixColor;\n + uniform lowp float preMultipliedAlpha;\n \n + lowp vec4 visualMixColor()\n + {\n + return vec4( mixColor.rgb * mix( 1.0, mixColor.a, preMultipliedAlpha ), mixColor.a );\n + }\n void main()\n {\n - gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n + gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor * visualMixColor();\n }\n ); @@ -132,12 +143,19 @@ const char* FRAGMENT_SHADER_ATLAS_CLAMP = DALI_COMPOSE_SHADER( uniform sampler2D sTexture;\n uniform mediump vec4 uAtlasRect;\n uniform lowp vec4 uColor;\n + uniform lowp vec4 mixColor;\n + uniform lowp float preMultipliedAlpha;\n \n - void main()\n + lowp vec4 visualMixColor()\n {\n - mediump vec2 texCoord = clamp( mix( uAtlasRect.xy, uAtlasRect.zw, vTexCoord ), uAtlasRect.xy, uAtlasRect.zw );\n - gl_FragColor = texture2D( sTexture, texCoord ) * uColor;\n + return vec4( mixColor.rgb * mix( 1.0, mixColor.a, preMultipliedAlpha ), mixColor.a );\n }\n + \n + void main()\n + {\n + mediump vec2 texCoord = clamp( mix( uAtlasRect.xy, uAtlasRect.zw, vTexCoord ), uAtlasRect.xy, uAtlasRect.zw );\n + gl_FragColor = texture2D( sTexture, texCoord ) * uColor * visualMixColor();\n + }\n ); const char* FRAGMENT_SHADER_ATLAS_VARIOUS_WRAP = DALI_COMPOSE_SHADER( @@ -147,6 +165,8 @@ const char* FRAGMENT_SHADER_ATLAS_VARIOUS_WRAP = DALI_COMPOSE_SHADER( // WrapMode -- 0: CLAMP; 1: REPEAT; 2: REFLECT; uniform lowp vec2 wrapMode;\n uniform lowp vec4 uColor;\n + uniform lowp vec4 mixColor;\n + uniform lowp float preMultipliedAlpha;\n \n mediump float wrapCoordinate( mediump vec2 range, mediump float coordinate, lowp float wrap )\n {\n @@ -158,11 +178,16 @@ const char* FRAGMENT_SHADER_ATLAS_VARIOUS_WRAP = DALI_COMPOSE_SHADER( return clamp( mix(range.x, range.y, coord), range.x, range.y ); }\n \n + lowp vec4 visualMixColor()\n + {\n + return vec4( mixColor.rgb * mix( 1.0, mixColor.a, preMultipliedAlpha ), mixColor.a );\n + }\n + \n void main()\n {\n - mediump vec2 texCoord = vec2( wrapCoordinate( uAtlasRect.xz, vTexCoord.x, wrapMode.x ), - wrapCoordinate( uAtlasRect.yw, vTexCoord.y, wrapMode.y ) );\n - gl_FragColor = texture2D( sTexture, texCoord ) * uColor;\n + mediump vec2 texCoord = vec2( wrapCoordinate( uAtlasRect.xz, vTexCoord.x, wrapMode.x ), + wrapCoordinate( uAtlasRect.yw, vTexCoord.y, wrapMode.y ) );\n + gl_FragColor = texture2D( sTexture, texCoord ) * uColor * visualMixColor();\n }\n ); @@ -173,11 +198,6 @@ Geometry CreateGeometry( VisualFactoryCache& factoryCache, ImageDimensions gridS if( gridSize == ImageDimensions( 1, 1 ) ) { geometry = factoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY ); - if( !geometry ) - { - geometry = VisualFactoryCache::CreateQuadGeometry(); - factoryCache.SaveGeometry( VisualFactoryCache::QUAD_GEOMETRY, geometry ); - } } else { @@ -189,9 +209,16 @@ Geometry CreateGeometry( VisualFactoryCache& factoryCache, ImageDimensions gridS } // unnamed namespace -ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache ) +ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache, + const std::string& imageUrl, + const Property::Map& properties, + ImageDimensions size, + FittingMode::Type fittingMode, + Dali::SamplingMode::Type samplingMode ) { - return new ImageVisual( factoryCache ); + ImageVisualPtr imageVisualPtr( new ImageVisual( factoryCache, imageUrl, size, fittingMode, samplingMode ) ); + imageVisualPtr->SetProperties( properties ); + return imageVisualPtr; } ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache, @@ -208,21 +235,6 @@ ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache, const Image& return new ImageVisual( factoryCache, image ); } -ImageVisual::ImageVisual( VisualFactoryCache& factoryCache ) -: Visual::Base( factoryCache ), - mImage(), - mPixels(), - mPixelArea( FULL_TEXTURE_RECT ), - mPlacementActor(), - mImageUrl(), - mDesiredSize(), - mFittingMode( FittingMode::DEFAULT ), - mSamplingMode( SamplingMode::DEFAULT ), - mWrapModeU( WrapMode::DEFAULT ), - mWrapModeV( WrapMode::DEFAULT ) -{ -} - ImageVisual::ImageVisual( VisualFactoryCache& factoryCache, const std::string& imageUrl, ImageDimensions size, @@ -263,93 +275,155 @@ ImageVisual::~ImageVisual() void ImageVisual::DoSetProperties( const Property::Map& propertyMap ) { - Property::Value* imageURLValue = propertyMap.Find( Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME ); - if( imageURLValue ) + // Url is already received in constructor + for( Property::Map::SizeType iter = 0; iter < propertyMap.Count(); ++iter ) { - imageURLValue->Get( mImageUrl ); - if( !mImageUrl.empty() ) + KeyValuePair keyValue = propertyMap.GetKeyValue( iter ); + if( keyValue.first.type == Property::Key::INDEX ) { - mImage.Reset(); + DoSetProperty( keyValue.first.indexKey, keyValue.second ); } - - Property::Value* fittingValue = propertyMap.Find( Toolkit::ImageVisual::Property::FITTING_MODE, IMAGE_FITTING_MODE ); - if( fittingValue ) + else { - int value; - Scripting::GetEnumerationProperty( *fittingValue, FITTING_MODE_TABLE, FITTING_MODE_TABLE_COUNT, value ); - mFittingMode = Dali::FittingMode::Type( value ); + if( keyValue.first == IMAGE_FITTING_MODE ) + { + DoSetProperty( Toolkit::ImageVisual::Property::FITTING_MODE, keyValue.second ); + } + else if( keyValue.first == IMAGE_SAMPLING_MODE ) + { + DoSetProperty( Toolkit::ImageVisual::Property::SAMPLING_MODE, keyValue.second ); + } + else if( keyValue.first == IMAGE_DESIRED_WIDTH ) + { + DoSetProperty( Toolkit::ImageVisual::Property::DESIRED_WIDTH, keyValue.second ); + } + else if( keyValue.first == IMAGE_DESIRED_HEIGHT ) + { + DoSetProperty( Toolkit::ImageVisual::Property::DESIRED_HEIGHT, keyValue.second ); + } + else if( keyValue.first == PIXEL_AREA_UNIFORM_NAME ) + { + DoSetProperty( Toolkit::ImageVisual::Property::PIXEL_AREA, keyValue.second ); + } + else if( keyValue.first == IMAGE_WRAP_MODE_U ) + { + DoSetProperty( Toolkit::ImageVisual::Property::WRAP_MODE_U, keyValue.second ); + } + else if( keyValue.first == IMAGE_WRAP_MODE_V ) + { + DoSetProperty( Toolkit::ImageVisual::Property::WRAP_MODE_V, keyValue.second ); + } + else if( keyValue.first == SYNCHRONOUS_LOADING ) + { + DoSetProperty( Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING, keyValue.second ); + } } + } - Property::Value* samplingValue = propertyMap.Find( Toolkit::ImageVisual::Property::SAMPLING_MODE, IMAGE_SAMPLING_MODE ); - if( samplingValue ) + if( mImpl->mFlags & Impl::IS_SYNCHRONOUS_RESOURCE_LOADING && mImageUrl.size() > 0u ) + { + // if sync loading is required, the loading should start + // immediately when new image url is set or the actor is off stage + // ( for on-stage actor with image url unchanged, resource loading + // is already finished ) + LoadResourceSynchronously(); + } +} + +void ImageVisual::DoSetProperty( Property::Index index, const Property::Value& value ) +{ + switch( index ) + { + case Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING: { - int value; - Scripting::GetEnumerationProperty( *samplingValue, SAMPLING_MODE_TABLE, SAMPLING_MODE_TABLE_COUNT, value ); - mSamplingMode = Dali::SamplingMode::Type( value ); + bool sync; + if( value.Get( sync ) ) + { + if( sync ) + { + mImpl->mFlags |= Impl::IS_SYNCHRONOUS_RESOURCE_LOADING; + } + else + { + mImpl->mFlags &= ~Impl::IS_SYNCHRONOUS_RESOURCE_LOADING; + } + } + else + { + DALI_LOG_ERROR("ImageVisual: synchronousLoading property has incorrect type\n"); + } + break; } - int desiredWidth = 0; - Property::Value* desiredWidthValue = propertyMap.Find( Toolkit::ImageVisual::Property::DESIRED_WIDTH, IMAGE_DESIRED_WIDTH ); - if( desiredWidthValue ) + case Toolkit::ImageVisual::Property::DESIRED_WIDTH: { - desiredWidthValue->Get( desiredWidth ); + float desiredWidth; + if( value.Get( desiredWidth ) ) + { + mDesiredSize.SetWidth( desiredWidth ); + } + else + { + DALI_LOG_ERROR("ImageVisual: desiredWidth property has incorrect type\n"); + } + break; } - int desiredHeight = 0; - Property::Value* desiredHeightValue = propertyMap.Find( Toolkit::ImageVisual::Property::DESIRED_HEIGHT, IMAGE_DESIRED_HEIGHT ); - if( desiredHeightValue ) + case Toolkit::ImageVisual::Property::DESIRED_HEIGHT: { - desiredHeightValue->Get( desiredHeight ); + float desiredHeight; + if( value.Get( desiredHeight ) ) + { + mDesiredSize.SetHeight( desiredHeight ); + } + else + { + DALI_LOG_ERROR("ImageVisual: desiredHeight property has incorrect type\n"); + } + break; } - Property::Value* pixelAreaValue = propertyMap.Find( Toolkit::ImageVisual::Property::PIXEL_AREA, PIXEL_AREA_UNIFORM_NAME ); - if( pixelAreaValue ) + case Toolkit::ImageVisual::Property::FITTING_MODE: { - pixelAreaValue->Get( mPixelArea ); + int fittingMode; + Scripting::GetEnumerationProperty( value, FITTING_MODE_TABLE, FITTING_MODE_TABLE_COUNT, fittingMode ); + mFittingMode = Dali::FittingMode::Type( fittingMode ); + break; } - Property::Value* wrapModeValueU = propertyMap.Find( Toolkit::ImageVisual::Property::WRAP_MODE_U, IMAGE_WRAP_MODE_U ); - if( wrapModeValueU ) + case Toolkit::ImageVisual::Property::SAMPLING_MODE: { - int value; - Scripting::GetEnumerationProperty( *wrapModeValueU, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, value ); - mWrapModeU = Dali::WrapMode::Type( value ); + int samplingMode; + Scripting::GetEnumerationProperty( value, SAMPLING_MODE_TABLE, SAMPLING_MODE_TABLE_COUNT, samplingMode ); + mSamplingMode = Dali::SamplingMode::Type( samplingMode ); + break; } - Property::Value* wrapModeValueV = propertyMap.Find( Toolkit::ImageVisual::Property::WRAP_MODE_V, IMAGE_WRAP_MODE_V ); - if( wrapModeValueV ) + case Toolkit::ImageVisual::Property::PIXEL_AREA: { - int value; - Scripting::GetEnumerationProperty( *wrapModeValueV, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, value ); - mWrapModeV = Dali::WrapMode::Type( value ); + value.Get( mPixelArea ); + break; } - mDesiredSize = ImageDimensions( desiredWidth, desiredHeight ); - } - - Property::Value* syncLoading = propertyMap.Find( Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING, SYNCHRONOUS_LOADING ); - if( syncLoading ) - { - bool sync; - syncLoading->Get( sync ); - if( sync ) + case Toolkit::ImageVisual::Property::WRAP_MODE_U: { - mImpl->mFlags |= Impl::IS_SYNCHRONOUS_RESOURCE_LOADING; - // if sync loading is required, the loading should start immediately when new image url is set or the actor is off stage - // ( for on-stage actor with image url unchanged, resource loading is already finished) - if( imageURLValue ) - { - LoadResourceSynchronously(); - } + int wrapMode; + Scripting::GetEnumerationProperty( value, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, wrapMode ); + mWrapModeU = Dali::WrapMode::Type( wrapMode ); + break; } - else + + case Toolkit::ImageVisual::Property::WRAP_MODE_V: { - mImpl->mFlags &= ~Impl::IS_SYNCHRONOUS_RESOURCE_LOADING; + int wrapMode; + Scripting::GetEnumerationProperty( value, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, wrapMode ); + mWrapModeV = Dali::WrapMode::Type( wrapMode ); + break; } } } -void ImageVisual::GetNaturalSize( Vector2& naturalSize ) const +void ImageVisual::GetNaturalSize( Vector2& naturalSize ) { if(mImage) { @@ -409,6 +483,9 @@ void ImageVisual::CreateRenderer( TextureSet& textures ) mImpl->mRenderer = Renderer::New( geometry, shader ); DALI_ASSERT_DEBUG( textures ); mImpl->mRenderer.SetTextures( textures ); + + //Register transform properties + mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT ); } void ImageVisual::CreateNativeImageRenderer( NativeImage& nativeImage ) @@ -457,6 +534,9 @@ void ImageVisual::CreateNativeImageRenderer( NativeImage& nativeImage ) } mImpl->mRenderer = Renderer::New( geometry, shader ); + + //Register transform properties + mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT ); } @@ -533,21 +613,22 @@ TextureSet ImageVisual::CreateTextureSet( Vector4& textureRect, const std::strin void ImageVisual::InitializeRenderer( const std::string& imageUrl ) { - if( imageUrl.empty() ) - { - return; - } - mImageUrl = imageUrl; - mImpl->mRenderer.Reset(); mImpl->mFlags &= ~Impl::IS_ATLASING_APPLIED; if( !mImpl->mCustomShader && - ( strncasecmp( imageUrl.c_str(), HTTP_URL, sizeof(HTTP_URL) -1 ) != 0 ) && // ignore remote images + ( strncasecmp( imageUrl.c_str(), HTTP_URL, sizeof(HTTP_URL) -1 ) != 0 ) && // dont atlas remote images ( strncasecmp( imageUrl.c_str(), HTTPS_URL, sizeof(HTTPS_URL) -1 ) != 0 ) ) { bool defaultWrapMode = mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE; - bool cacheable = defaultWrapMode && mPixelArea == FULL_TEXTURE_RECT; + bool defaultTransform = mImpl->mTransform.mSize == Vector2::ONE && + mImpl->mTransform.mOffset == Vector2::ZERO && + mImpl->mTransform.mOffsetSizeMode == Vector4::ZERO && + mImpl->mTransform.mOrigin == Toolkit::Align::CENTER && + mImpl->mTransform.mAnchorPoint == Toolkit::Align::CENTER; + + bool cacheable = defaultWrapMode && defaultTransform && mPixelArea == FULL_TEXTURE_RECT; + mImpl->mFlags &= ~Impl::IS_FROM_CACHE; if( cacheable ) // fetch the renderer from cache if exist @@ -611,11 +692,7 @@ void ImageVisual::InitializeRenderer( const Image& image ) // reuse existing code for regular images CreateRenderer( textures ); } - - if( image ) - { - ApplyImageToSampler( image ); - } + ApplyImageToSampler( image ); } void ImageVisual::UploadCompleted() @@ -632,17 +709,22 @@ void ImageVisual::UploadCompleted() void ImageVisual::DoSetOnStage( Actor& actor ) { - mPlacementActor = actor; - if( !mImageUrl.empty() ) { InitializeRenderer( mImageUrl ); } - else + else if ( mImage ) { InitializeRenderer( mImage ); } + if ( !mImpl->mRenderer ) + { + return; + } + + mPlacementActor = actor; + if( mPixelArea != FULL_TEXTURE_RECT ) { mImpl->mRenderer.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, mPixelArea ); @@ -657,25 +739,24 @@ void ImageVisual::DoSetOnStage( Actor& actor ) void ImageVisual::DoSetOffStage( Actor& actor ) { + // Visual::Base::SetOffStage only calls DoSetOffStage if mRenderer exists (is on onstage) + //If we own the image then make sure we release it when we go off stage + actor.RemoveRenderer( mImpl->mRenderer); if( !mImageUrl.empty() ) { - actor.RemoveRenderer( mImpl->mRenderer ); CleanCache(mImageUrl); mImage.Reset(); } - else - { - actor.RemoveRenderer( mImpl->mRenderer ); - mImpl->mRenderer.Reset(); - } + + mImpl->mRenderer.Reset(); mPlacementActor.Reset(); } void ImageVisual::DoCreatePropertyMap( Property::Map& map ) const { map.Clear(); - map.Insert( Toolkit::VisualProperty::TYPE, Toolkit::Visual::IMAGE ); + map.Insert( Toolkit::DevelVisual::Property::TYPE, Toolkit::Visual::IMAGE ); bool sync = IsSynchronousResourceLoading(); map.Insert( SYNCHRONOUS_LOADING, sync ); @@ -705,15 +786,12 @@ void ImageVisual::DoCreatePropertyMap( Property::Map& map ) const map.Insert( Toolkit::ImageVisual::Property::WRAP_MODE_V, mWrapModeV ); } -void ImageVisual::DoSetProperty( Dali::Property::Index index, const Dali::Property::Value& propertyValue ) +void ImageVisual::OnSetTransform() { - // TODO -} - -Dali::Property::Value ImageVisual::DoGetProperty( Dali::Property::Index index ) -{ - // TODO - return Dali::Property::Value(); + if( mImpl->mRenderer ) + { + mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT ); + } } Shader ImageVisual::GetImageShader( VisualFactoryCache& factoryCache, bool atlasing, bool defaultTextureWrapping ) @@ -727,6 +805,7 @@ Shader ImageVisual::GetImageShader( VisualFactoryCache& factoryCache, bool atlas if( !shader ) { shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_ATLAS_CLAMP ); + shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT ); factoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP, shader ); } } @@ -736,6 +815,7 @@ Shader ImageVisual::GetImageShader( VisualFactoryCache& factoryCache, bool atlas if( !shader ) { shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_ATLAS_VARIOUS_WRAP ); + shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT ); factoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_CUSTOM_WRAP, shader ); } } @@ -746,10 +826,11 @@ Shader ImageVisual::GetImageShader( VisualFactoryCache& factoryCache, bool atlas if( !shader ) { shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_NO_ATLAS ); + shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT ); factoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER, shader ); } } - shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT ); + return shader; }