[Vulkan] Added 'builtin' shaders
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / image / image-visual.cpp
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali-toolkit/internal/visuals/image/image-visual.h>
20
21 // EXTERNAL HEADERS
22 #include <cstring> // for strlen()
23 #include <dali/public-api/actors/layer.h>
24 #include <dali/public-api/common/stage.h>
25 #include <dali/public-api/images/resource-image.h>
26 #include <dali/public-api/images/native-image.h>
27 #include <dali/devel-api/images/texture-set-image.h>
28 #include <dali/devel-api/adaptor-framework/image-loading.h>
29 #include <dali/devel-api/scripting/enum-helper.h>
30 #include <dali/devel-api/scripting/scripting.h>
31 #include <dali/devel-api/rendering/shader-devel.h>
32 #include <dali/integration-api/debug.h>
33
34 // INTERNAL HEADERS
35 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
36 #include <dali-toolkit/public-api/visuals/visual-properties.h>
37 #include <dali-toolkit/internal/visuals/texture-manager-impl.h>
38 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
39 #include <dali-toolkit/internal/visuals/visual-factory-impl.h>
40 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
41 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
42 #include <dali-toolkit/internal/visuals/image-atlas-manager.h>
43 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
44 #include <dali-toolkit/internal/visuals/visual-url.h>
45
46 #include <dali-toolkit/devel-api/graphics/builtin-shader-extern-gen.h>
47
48 namespace Dali
49 {
50
51 namespace Toolkit
52 {
53
54 namespace Internal
55 {
56
57 namespace
58 {
59
60 // property names
61 const char * const IMAGE_FITTING_MODE( "fittingMode" );
62 const char * const IMAGE_SAMPLING_MODE( "samplingMode" );
63 const char * const IMAGE_DESIRED_WIDTH( "desiredWidth" );
64 const char * const IMAGE_DESIRED_HEIGHT( "desiredHeight" );
65 const char * const SYNCHRONOUS_LOADING( "synchronousLoading" );
66 const char * const IMAGE_ATLASING("atlasing");
67 const char * const ALPHA_MASK_URL("alphaMaskUrl");
68
69 // fitting modes
70 DALI_ENUM_TO_STRING_TABLE_BEGIN( FITTING_MODE )
71 DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::FittingMode, SHRINK_TO_FIT )
72 DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::FittingMode, SCALE_TO_FILL )
73 DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::FittingMode, FIT_WIDTH )
74 DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::FittingMode, FIT_HEIGHT )
75 DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::FittingMode, DEFAULT )
76 DALI_ENUM_TO_STRING_TABLE_END( FITTING_MODE )
77
78 // sampling modes
79 DALI_ENUM_TO_STRING_TABLE_BEGIN( SAMPLING_MODE )
80 DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::SamplingMode, BOX )
81 DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::SamplingMode, NEAREST )
82 DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::SamplingMode, LINEAR )
83 DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::SamplingMode, BOX_THEN_NEAREST )
84 DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::SamplingMode, BOX_THEN_LINEAR )
85 DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::SamplingMode, NO_FILTER )
86 DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::SamplingMode, DONT_CARE )
87 DALI_ENUM_TO_STRING_TABLE_END( SAMPLING_MODE )
88
89 // wrap modes
90 DALI_ENUM_TO_STRING_TABLE_BEGIN( WRAP_MODE )
91 DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::WrapMode, DEFAULT )
92 DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::WrapMode, CLAMP_TO_EDGE )
93 DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::WrapMode, REPEAT )
94 DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::WrapMode, MIRRORED_REPEAT )
95 DALI_ENUM_TO_STRING_TABLE_END( WRAP_MODE )
96
97 // load policies
98 DALI_ENUM_TO_STRING_TABLE_BEGIN( LOAD_POLICY )
99 DALI_ENUM_TO_STRING_WITH_SCOPE( DevelImageVisual::LoadPolicy, IMMEDIATE )
100 DALI_ENUM_TO_STRING_WITH_SCOPE( DevelImageVisual::LoadPolicy, ATTACHED )
101 DALI_ENUM_TO_STRING_TABLE_END( LOAD_POLICY )
102
103 // release policies
104 DALI_ENUM_TO_STRING_TABLE_BEGIN( RELEASE_POLICY )
105 DALI_ENUM_TO_STRING_WITH_SCOPE( DevelImageVisual::ReleasePolicy, DETACHED )
106 DALI_ENUM_TO_STRING_WITH_SCOPE( DevelImageVisual::ReleasePolicy, DESTROYED )
107 DALI_ENUM_TO_STRING_WITH_SCOPE( DevelImageVisual::ReleasePolicy, NEVER )
108 DALI_ENUM_TO_STRING_TABLE_END( RELEASE_POLICY )
109
110 const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
111
112 const char* DEFAULT_SAMPLER_TYPENAME = "sampler2D";
113
114 const float PIXEL_ALIGN_ON = 1.0f;
115 const float PIXEL_ALIGN_OFF = 0.0f;
116
117 const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
118   attribute mediump vec2 aPosition;\n
119   uniform mediump mat4 uModelMatrix;\n
120   uniform mediump mat4 uViewMatrix;\n
121   uniform mediump mat4 uProjection;\n
122   uniform mediump vec3 uSize;\n
123   uniform mediump vec4 pixelArea;
124   varying mediump vec2 vTexCoord;\n
125   uniform lowp float uPixelAligned;\n
126   \n
127   //Visual size and offset
128   uniform mediump vec2 offset;\n
129   uniform mediump vec2 size;\n
130   uniform mediump vec4 offsetSizeMode;\n
131   uniform mediump vec2 origin;\n
132   uniform mediump vec2 anchorPoint;\n
133 \n
134   vec4 ComputeVertexPosition()\n
135   {\n
136     vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw );\n
137     vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);\n
138     return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );\n
139   }\n
140 \n
141   void main()\n
142   {\n
143     mediump vec4 vertexPosition = uViewMatrix * uModelMatrix * ComputeVertexPosition();\n
144     vec4 alignedVertexPosition = vertexPosition;\n
145     alignedVertexPosition.xy = floor ( vertexPosition.xy );\n // Pixel alignment
146     vertexPosition = uProjection * mix( vertexPosition, alignedVertexPosition, uPixelAligned );\n
147     vTexCoord = pixelArea.xy+pixelArea.zw*(aPosition + vec2(0.5) );\n
148     gl_Position = vertexPosition;\n
149   }\n
150 );
151
152 const char* FRAGMENT_SHADER_NO_ATLAS = DALI_COMPOSE_SHADER(
153   varying mediump vec2 vTexCoord;\n
154   uniform sampler2D sTexture;\n
155   uniform lowp vec4 uColor;\n
156   uniform lowp vec3 mixColor;\n
157   uniform lowp float opacity;\n
158   uniform lowp float preMultipliedAlpha;\n
159   \n
160   lowp vec4 visualMixColor()\n
161   {\n
162     return vec4( mixColor * mix( 1.0, opacity, preMultipliedAlpha ), opacity );\n
163   }\n
164   void main()\n
165   {\n
166       gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor * visualMixColor();\n
167   }\n
168 );
169
170 const char* FRAGMENT_SHADER_ATLAS_CLAMP = DALI_COMPOSE_SHADER(
171     varying mediump vec2 vTexCoord;\n
172     uniform sampler2D sTexture;\n
173     uniform mediump vec4 uAtlasRect;\n
174     uniform lowp vec4 uColor;\n
175     uniform lowp vec3 mixColor;\n
176     uniform lowp float opacity;\n
177     uniform lowp float preMultipliedAlpha;\n
178     \n
179     lowp vec4 visualMixColor()\n
180     {\n
181         return vec4( mixColor * mix( 1.0, opacity, preMultipliedAlpha ), opacity );\n
182     }\n
183     \n
184     void main()\n
185     {\n
186         mediump vec2 texCoord = clamp( mix( uAtlasRect.xy, uAtlasRect.zw, vTexCoord ), uAtlasRect.xy, uAtlasRect.zw );\n
187         gl_FragColor = texture2D( sTexture, texCoord ) * uColor * visualMixColor();\n
188      }\n
189 );
190
191 const char* FRAGMENT_SHADER_ATLAS_VARIOUS_WRAP = DALI_COMPOSE_SHADER(
192     varying mediump vec2 vTexCoord;\n
193     uniform sampler2D sTexture;\n
194     uniform mediump vec4 uAtlasRect;\n
195     // WrapMode -- 0: CLAMP; 1: REPEAT; 2: REFLECT;
196     uniform lowp vec2 wrapMode;\n
197     uniform lowp vec4 uColor;\n
198     uniform lowp vec3 mixColor;\n
199     uniform lowp float opacity;\n
200     uniform lowp float preMultipliedAlpha;\n
201     \n
202     mediump float wrapCoordinate( mediump vec2 range, mediump float coordinate, lowp float wrap )\n
203     {\n
204       mediump float coord;\n
205       if( wrap > 1.5 )\n // REFLECT
206         coord = 1.0-abs(fract(coordinate*0.5)*2.0 - 1.0);\n
207       else \n// warp == 0 or 1
208         coord = mix(coordinate, fract( coordinate ), wrap);\n
209       return clamp( mix(range.x, range.y, coord), range.x, range.y );
210     }\n
211     \n
212     lowp vec4 visualMixColor()\n
213     {\n
214       return vec4( mixColor * mix( 1.0, opacity, preMultipliedAlpha ), opacity );\n
215     }\n
216     \n
217     void main()\n
218     {\n
219         mediump vec2 texCoord = vec2( wrapCoordinate( uAtlasRect.xz, vTexCoord.x, wrapMode.x ),
220                                       wrapCoordinate( uAtlasRect.yw, vTexCoord.y, wrapMode.y ) );\n
221         gl_FragColor = texture2D( sTexture, texCoord ) * uColor * visualMixColor();\n
222     }\n
223 );
224
225 Geometry CreateGeometry( VisualFactoryCache& factoryCache, ImageDimensions gridSize )
226 {
227   Geometry geometry;
228
229   if( gridSize == ImageDimensions( 1, 1 ) )
230   {
231     geometry = factoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY );
232   }
233   else
234   {
235     geometry = VisualFactoryCache::CreateGridGeometry( gridSize );
236   }
237
238   return geometry;
239 }
240
241 } // unnamed namespace
242
243 ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache,
244                                  const VisualUrl& imageUrl,
245                                  const Property::Map& properties,
246                                  ImageDimensions size,
247                                  FittingMode::Type fittingMode,
248                                  Dali::SamplingMode::Type samplingMode )
249 {
250   ImageVisualPtr imageVisualPtr( new ImageVisual( factoryCache, imageUrl, size, fittingMode, samplingMode ) );
251   imageVisualPtr->SetProperties( properties );
252   return imageVisualPtr;
253 }
254
255 ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache,
256                                  const VisualUrl& imageUrl,
257                                  ImageDimensions size,
258                                  FittingMode::Type fittingMode,
259                                  Dali::SamplingMode::Type samplingMode )
260 {
261   return new ImageVisual( factoryCache, imageUrl, size, fittingMode, samplingMode );
262 }
263
264 ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache, const Image& image )
265 {
266   return new ImageVisual( factoryCache, image );
267 }
268
269 ImageVisual::ImageVisual( VisualFactoryCache& factoryCache,
270                           const VisualUrl& imageUrl,
271                           ImageDimensions size,
272                           FittingMode::Type fittingMode,
273                           Dali::SamplingMode::Type samplingMode )
274 : Visual::Base( factoryCache ),
275   mImage(),
276   mPixelArea( FULL_TEXTURE_RECT ),
277   mPlacementActor(),
278   mImageUrl( imageUrl ),
279   mMaskingData( ),
280   mDesiredSize( size ),
281   mTextureId( TextureManager::INVALID_TEXTURE_ID ),
282   mFittingMode( fittingMode ),
283   mSamplingMode( samplingMode ),
284   mWrapModeU( WrapMode::DEFAULT ),
285   mWrapModeV( WrapMode::DEFAULT ),
286   mLoadPolicy( DevelImageVisual::LoadPolicy::ATTACHED ),
287   mReleasePolicy( DevelImageVisual::ReleasePolicy::DETACHED ),
288   mAttemptAtlasing( false ),
289   mLoading( false )
290 {
291 }
292
293 ImageVisual::ImageVisual( VisualFactoryCache& factoryCache, const Image& image )
294 : Visual::Base( factoryCache ),
295   mImage( image ),
296   mPixelArea( FULL_TEXTURE_RECT ),
297   mPlacementActor(),
298   mImageUrl(),
299   mMaskingData( ),
300   mDesiredSize(),
301   mTextureId( TextureManager::INVALID_TEXTURE_ID ),
302   mFittingMode( FittingMode::DEFAULT ),
303   mSamplingMode( SamplingMode::DEFAULT ),
304   mWrapModeU( WrapMode::DEFAULT ),
305   mWrapModeV( WrapMode::DEFAULT ),
306   mLoadPolicy( DevelImageVisual::LoadPolicy::ATTACHED ),
307   mReleasePolicy( DevelImageVisual::ReleasePolicy::DESTROYED ),
308   mAttemptAtlasing( false ),
309   mLoading( false ),
310   mOrientationCorrection( true )
311 {
312 }
313
314 ImageVisual::~ImageVisual()
315 {
316   if( Stage::IsInstalled() )
317   {
318     if( mMaskingData )
319     {
320       // TextureManager could have been deleted before the actor that contains this
321       // ImageVisual is destroyed (e.g. due to stage shutdown). Ensure the stage
322       // is still valid before accessing texture manager.
323       if( mMaskingData->mAlphaMaskId != TextureManager::INVALID_TEXTURE_ID )
324       {
325         TextureManager& textureManager = mFactoryCache.GetTextureManager();
326         textureManager.Remove( mMaskingData->mAlphaMaskId );
327       }
328     }
329
330     // ImageVisual destroyed so remove texture unless ReleasePolicy is set to never release
331     if( ( mTextureId != TextureManager::INVALID_TEXTURE_ID  ) && ( mReleasePolicy != DevelImageVisual::ReleasePolicy::NEVER ) )
332     {
333       RemoveTexture();
334     }
335   }
336 }
337
338 void ImageVisual::DoSetProperties( const Property::Map& propertyMap )
339 {
340   // Url is already received in constructor
341   for( Property::Map::SizeType iter = 0; iter < propertyMap.Count(); ++iter )
342   {
343     KeyValuePair keyValue = propertyMap.GetKeyValue( iter );
344     if( keyValue.first.type == Property::Key::INDEX )
345     {
346       DoSetProperty( keyValue.first.indexKey, keyValue.second );
347     }
348     else
349     {
350       if( keyValue.first == IMAGE_FITTING_MODE )
351       {
352         DoSetProperty( Toolkit::ImageVisual::Property::FITTING_MODE, keyValue.second );
353       }
354       else if( keyValue.first == IMAGE_SAMPLING_MODE )
355       {
356         DoSetProperty( Toolkit::ImageVisual::Property::SAMPLING_MODE, keyValue.second );
357       }
358       else if( keyValue.first == IMAGE_DESIRED_WIDTH )
359       {
360         DoSetProperty( Toolkit::ImageVisual::Property::DESIRED_WIDTH, keyValue.second );
361       }
362       else if( keyValue.first == IMAGE_DESIRED_HEIGHT )
363       {
364         DoSetProperty( Toolkit::ImageVisual::Property::DESIRED_HEIGHT, keyValue.second );
365       }
366       else if( keyValue.first == PIXEL_AREA_UNIFORM_NAME )
367       {
368         DoSetProperty( Toolkit::ImageVisual::Property::PIXEL_AREA, keyValue.second );
369       }
370       else if( keyValue.first == IMAGE_WRAP_MODE_U )
371       {
372         DoSetProperty( Toolkit::ImageVisual::Property::WRAP_MODE_U, keyValue.second );
373       }
374       else if( keyValue.first == IMAGE_WRAP_MODE_V )
375       {
376         DoSetProperty( Toolkit::ImageVisual::Property::WRAP_MODE_V, keyValue.second );
377       }
378       else if( keyValue.first == SYNCHRONOUS_LOADING )
379       {
380         DoSetProperty( Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING, keyValue.second );
381       }
382       else if( keyValue.first == IMAGE_ATLASING )
383       {
384         DoSetProperty( Toolkit::ImageVisual::Property::ATLASING, keyValue.second );
385       }
386       else if( keyValue.first == ALPHA_MASK_URL )
387       {
388         DoSetProperty( Toolkit::ImageVisual::Property::ALPHA_MASK_URL, keyValue.second );
389       }
390       else if( keyValue.first == MASK_CONTENT_SCALE_NAME )
391       {
392         DoSetProperty( Toolkit::ImageVisual::Property::MASK_CONTENT_SCALE, keyValue.second );
393       }
394       else if( keyValue.first == CROP_TO_MASK_NAME )
395       {
396         DoSetProperty( Toolkit::ImageVisual::Property::CROP_TO_MASK, keyValue.second );
397       }
398       else if ( keyValue.first == LOAD_POLICY_NAME )
399       {
400         DoSetProperty( Toolkit::DevelImageVisual::Property::LOAD_POLICY, keyValue.second );
401       }
402       else if( keyValue.first == RELEASE_POLICY_NAME )
403       {
404         DoSetProperty( Toolkit::DevelImageVisual::Property::RELEASE_POLICY, keyValue.second );
405       }
406       else if( keyValue.first == ORIENTATION_CORRECTION_NAME )
407       {
408         DoSetProperty( Toolkit::DevelImageVisual::Property::ORIENTATION_CORRECTION, keyValue.second );
409       }
410     }
411   }
412
413   // Load image immediately if LOAD_POLICY requires it
414   if ( mLoadPolicy == DevelImageVisual::LoadPolicy::IMMEDIATE )
415   {
416     auto attemptAtlasing = mAttemptAtlasing;
417     LoadTexture( attemptAtlasing, mAtlasRect, mTextures, mOrientationCorrection );
418   }
419 }
420
421 void ImageVisual::DoSetProperty( Property::Index index, const Property::Value& value )
422 {
423   switch( index )
424   {
425     case Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING:
426     {
427       bool sync;
428       if( value.Get( sync ) )
429       {
430         if( sync )
431         {
432           mImpl->mFlags |= Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
433         }
434         else
435         {
436           mImpl->mFlags &= ~Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
437         }
438       }
439       else
440       {
441         DALI_LOG_ERROR("ImageVisual: synchronousLoading property has incorrect type\n");
442       }
443       break;
444     }
445
446     case Toolkit::ImageVisual::Property::DESIRED_WIDTH:
447     {
448       float desiredWidth;
449       if( value.Get( desiredWidth ) )
450       {
451         mDesiredSize.SetWidth( desiredWidth );
452       }
453       else
454       {
455         DALI_LOG_ERROR("ImageVisual: desiredWidth property has incorrect type\n");
456       }
457       break;
458     }
459
460     case Toolkit::ImageVisual::Property::DESIRED_HEIGHT:
461     {
462       float desiredHeight;
463       if( value.Get( desiredHeight ) )
464       {
465         mDesiredSize.SetHeight( desiredHeight );
466       }
467       else
468       {
469         DALI_LOG_ERROR("ImageVisual: desiredHeight property has incorrect type\n");
470       }
471       break;
472     }
473
474     case Toolkit::ImageVisual::Property::FITTING_MODE:
475     {
476       int fittingMode;
477       Scripting::GetEnumerationProperty( value, FITTING_MODE_TABLE, FITTING_MODE_TABLE_COUNT, fittingMode );
478       mFittingMode = Dali::FittingMode::Type( fittingMode );
479       break;
480     }
481
482     case Toolkit::ImageVisual::Property::SAMPLING_MODE:
483     {
484       int samplingMode;
485       Scripting::GetEnumerationProperty( value, SAMPLING_MODE_TABLE, SAMPLING_MODE_TABLE_COUNT, samplingMode );
486       mSamplingMode = Dali::SamplingMode::Type( samplingMode );
487       break;
488     }
489
490     case Toolkit::ImageVisual::Property::PIXEL_AREA:
491     {
492       value.Get( mPixelArea );
493       break;
494     }
495
496     case Toolkit::ImageVisual::Property::WRAP_MODE_U:
497     {
498       int wrapMode;
499       Scripting::GetEnumerationProperty( value, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, wrapMode );
500       mWrapModeU = Dali::WrapMode::Type( wrapMode );
501       break;
502     }
503
504     case Toolkit::ImageVisual::Property::WRAP_MODE_V:
505     {
506       int wrapMode;
507       Scripting::GetEnumerationProperty( value, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, wrapMode );
508       mWrapModeV = Dali::WrapMode::Type( wrapMode );
509       break;
510     }
511
512     case Toolkit::ImageVisual::Property::ATLASING:
513     {
514       value.Get( mAttemptAtlasing );
515       break;
516     }
517
518     case Toolkit::ImageVisual::Property::ALPHA_MASK_URL:
519     {
520       std::string alphaUrl;
521       if( value.Get( alphaUrl ) )
522       {
523         AllocateMaskData();
524         // Immediately trigger the alpha mask loading (it may just get a cached value)
525         mMaskingData->mAlphaMaskUrl = alphaUrl;
526         TextureManager& textureManager = mFactoryCache.GetTextureManager();
527         mMaskingData->mAlphaMaskId = textureManager.RequestMaskLoad( alphaUrl );
528       }
529       break;
530     }
531
532     case Toolkit::ImageVisual::Property::MASK_CONTENT_SCALE:
533     {
534       float scale;
535       if( value.Get( scale ) )
536       {
537         AllocateMaskData();
538         mMaskingData->mContentScaleFactor = scale;
539       }
540       break;
541     }
542
543     case Toolkit::ImageVisual::Property::CROP_TO_MASK:
544     {
545       bool crop=false;
546       if( value.Get( crop ) )
547       {
548         AllocateMaskData();
549         mMaskingData->mCropToMask = crop;
550       }
551       break;
552     }
553
554     case Toolkit::DevelImageVisual::Property::RELEASE_POLICY:
555     {
556       int releasePolicy;
557       Scripting::GetEnumerationProperty( value, RELEASE_POLICY_TABLE, RELEASE_POLICY_TABLE_COUNT, releasePolicy );
558       mReleasePolicy = DevelImageVisual::ReleasePolicy::Type( releasePolicy );
559       break;
560     }
561
562     case Toolkit::DevelImageVisual::Property::LOAD_POLICY:
563     {
564       int loadPolicy;
565       Scripting::GetEnumerationProperty( value, LOAD_POLICY_TABLE, LOAD_POLICY_TABLE_COUNT, loadPolicy );
566       mLoadPolicy = DevelImageVisual::LoadPolicy::Type( loadPolicy );
567       break;
568     }
569     case Toolkit::DevelImageVisual::Property::ORIENTATION_CORRECTION:
570     {
571       bool orientationCorrection( mOrientationCorrection );
572       if( value.Get( orientationCorrection ) )
573       {
574         mOrientationCorrection = orientationCorrection;
575       }
576       break;
577     }
578   }
579 }
580
581 void ImageVisual::AllocateMaskData()
582 {
583   if( !mMaskingData )
584   {
585     mMaskingData.reset(new TextureManager::MaskingData());
586   }
587 }
588
589 void ImageVisual::GetNaturalSize( Vector2& naturalSize )
590 {
591   if(mImage)
592   {
593     naturalSize.x = mImage.GetWidth();
594     naturalSize.y = mImage.GetHeight();
595     return;
596   }
597   else if( mDesiredSize.GetWidth()>0 && mDesiredSize.GetHeight()>0)
598   {
599     naturalSize.x = mDesiredSize.GetWidth();
600     naturalSize.y = mDesiredSize.GetHeight();
601     return;
602   }
603   else if( mImpl->mRenderer ) // Check if we have a loaded image
604   {
605     auto textureSet = mImpl->mRenderer.GetTextures();
606
607     if( textureSet )
608     {
609       auto texture = textureSet.GetTexture(0);
610       naturalSize.x = texture.GetWidth();
611       naturalSize.y = texture.GetHeight();
612       return;
613     }
614   }
615
616   if( mMaskingData != NULL && mMaskingData->mAlphaMaskUrl.IsValid() &&
617            mMaskingData->mCropToMask )
618   {
619     ImageDimensions dimensions = Dali::GetClosestImageSize( mMaskingData->mAlphaMaskUrl.GetUrl() );
620     if( dimensions != ImageDimensions( 0, 0 ) )
621     {
622       naturalSize.x = dimensions.GetWidth();
623       naturalSize.y = dimensions.GetHeight();
624     }
625     return;
626   }
627   else if( mImageUrl.IsValid() )
628   {
629     if( mImageUrl.GetProtocolType() == VisualUrl::LOCAL )
630     {
631       ImageDimensions dimensions = Dali::GetClosestImageSize( mImageUrl.GetUrl() );
632
633       if( dimensions != ImageDimensions( 0, 0 ) )
634       {
635         naturalSize.x = dimensions.GetWidth();
636         naturalSize.y = dimensions.GetHeight();
637       }
638       else
639       {
640         Image brokenImage = VisualFactoryCache::GetBrokenVisualImage();
641
642         naturalSize.x = brokenImage.GetWidth();
643         naturalSize.y = brokenImage.GetWidth();
644       }
645       return;
646     }
647   }
648
649   naturalSize = Vector2::ZERO;
650 }
651
652 void ImageVisual::CreateRenderer( TextureSet& textureSet )
653 {
654   Geometry geometry;
655   Shader shader;
656
657   if( !mImpl->mCustomShader )
658   {
659     geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) );
660
661     shader = GetImageShader( mFactoryCache,
662                              mImpl->mFlags & Impl::IS_ATLASING_APPLIED,
663                              mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE );
664   }
665   else
666   {
667     geometry = CreateGeometry( mFactoryCache, mImpl->mCustomShader->mGridSize );
668     if( mImpl->mCustomShader->mVertexShader.empty() && mImpl->mCustomShader->mFragmentShader.empty() )
669     {
670       shader = GetImageShader( mFactoryCache, false, true );
671     }
672     else
673     {
674       //shader  = Shader::New( mImpl->mCustomShader->mVertexShader.empty() ? VERTEX_SHADER : mImpl->mCustomShader->mVertexShader,
675       //                       mImpl->mCustomShader->mFragmentShader.empty() ? FRAGMENT_SHADER_NO_ATLAS : mImpl->mCustomShader->mFragmentShader,
676       //                       mImpl->mCustomShader->mHints );
677       shader = DevelShader::New<uint32_t>(
678         GraphicsGetBuiltinShader( "SHADER_IMAGE_VISUAL_SHADER_VERT"),
679         GraphicsGetBuiltinShader( "SHADER_IMAGE_VISUAL_NO_ATLAS_SHADER_FRAG" ),
680                                   DevelShader::ShaderLanguage::SPIRV_1_0, Property::Map() );
681       if( mImpl->mCustomShader->mVertexShader.empty() )
682       {
683         shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
684       }
685     }
686   }
687
688   // Set pixel align off as default.
689   // ToDo: Pixel align causes issues such as rattling image animation.
690   // We should trun it off until issues are resolved
691   shader.RegisterProperty( PIXEL_ALIGNED_UNIFORM_NAME, PIXEL_ALIGN_OFF );
692
693   mImpl->mRenderer = Renderer::New( geometry, shader );
694   if( textureSet )
695   {
696     mImpl->mRenderer.SetTextures( textureSet );
697   }
698   // else still waiting for texture load to finish.
699
700   //Register transform properties
701   mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
702 }
703
704 void ImageVisual::CreateNativeImageRenderer( NativeImage& nativeImage )
705 {
706   Geometry geometry;
707   Shader shader;
708
709   std::string fragmentShader;
710   const char* fragmentPreFix = nativeImage.GetCustomFragmentPreFix();
711   const char* customSamplerTypename = nativeImage.GetCustomSamplerTypename();
712
713   if( fragmentPreFix )
714   {
715     fragmentShader = fragmentPreFix;
716     fragmentShader += "\n";
717   }
718
719   if( mImpl->mCustomShader && !mImpl->mCustomShader->mFragmentShader.empty() )
720   {
721     fragmentShader += mImpl->mCustomShader->mFragmentShader;
722   }
723   else
724   {
725     fragmentShader += FRAGMENT_SHADER_NO_ATLAS;
726   }
727
728   if( customSamplerTypename )
729   {
730     fragmentShader.replace( fragmentShader.find( DEFAULT_SAMPLER_TYPENAME ), strlen( DEFAULT_SAMPLER_TYPENAME ), customSamplerTypename );
731   }
732
733   if( !mImpl->mCustomShader )
734   {
735     geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) );
736
737     shader  = Shader::New( VERTEX_SHADER, fragmentShader );
738     shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
739   }
740   else
741   {
742     geometry = CreateGeometry( mFactoryCache, mImpl->mCustomShader->mGridSize );
743     shader  = Shader::New( mImpl->mCustomShader->mVertexShader.empty() ? VERTEX_SHADER : mImpl->mCustomShader->mVertexShader,
744                            fragmentShader,
745                            mImpl->mCustomShader->mHints );
746     if( mImpl->mCustomShader->mVertexShader.empty() )
747     {
748       shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
749     }
750   }
751
752   mImpl->mRenderer = Renderer::New( geometry, shader );
753
754   //Register transform properties
755   mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
756 }
757
758
759 bool ImageVisual::IsSynchronousResourceLoading() const
760 {
761   return mImpl->mFlags & Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
762 }
763
764 void ImageVisual::LoadTexture( bool& atlasing, Vector4& atlasRect, TextureSet& textures, bool orientationCorrection )
765 {
766   TextureManager& textureManager = mFactoryCache.GetTextureManager();
767
768   ImageAtlasManagerPtr atlasManager = nullptr;
769   AtlasUploadObserver* atlasUploadObserver = nullptr;
770   auto textureObserver = this;
771
772   if( atlasing )
773   {
774     atlasManager = mFactoryCache.GetAtlasManager();
775     atlasUploadObserver = this;
776   }
777
778   textures = textureManager.LoadTexture( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode,
779                                          mMaskingData, IsSynchronousResourceLoading(), mTextureId,
780                                          atlasRect, atlasing, mLoading, mWrapModeU,
781                                          mWrapModeV, textureObserver, atlasUploadObserver, atlasManager, mOrientationCorrection );
782 }
783
784 void ImageVisual::InitializeRenderer()
785 {
786   auto attemptAtlasing = ( ! mImpl->mCustomShader && mImageUrl.GetProtocolType() == VisualUrl::LOCAL && mAttemptAtlasing );
787
788   // texture set has to be created first as we need to know if atlasing succeeded or not
789   // when selecting the shader
790
791   if( mTextureId == TextureManager::INVALID_TEXTURE_ID && ! mTextures ) // Only load the texture once
792   {
793     LoadTexture( attemptAtlasing, mAtlasRect, mTextures, mOrientationCorrection );
794   }
795
796   if( attemptAtlasing ) // Flag needs to be set before creating renderer
797   {
798     mImpl->mFlags |= Impl::IS_ATLASING_APPLIED;
799   }
800   else
801   {
802     mImpl->mFlags &= ~Impl::IS_ATLASING_APPLIED;
803   }
804
805   CreateRenderer( mTextures );
806   mTextures.Reset(); // Visual should not keep a handle to the texture after this point.
807
808   if( attemptAtlasing ) // the texture is packed inside atlas
809   {
810     mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, mAtlasRect );
811
812     bool defaultWrapMode = mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE;
813
814     if( !defaultWrapMode ) // custom wrap mode
815     {
816       Vector2 wrapMode(mWrapModeU-WrapMode::CLAMP_TO_EDGE, mWrapModeV-WrapMode::CLAMP_TO_EDGE);
817       wrapMode.Clamp( Vector2::ZERO, Vector2( 2.f, 2.f ) );
818       mImpl->mRenderer.RegisterProperty( WRAP_MODE_UNIFORM_NAME, wrapMode );
819     }
820   }
821 }
822
823 void ImageVisual::InitializeRenderer( const Image& image )
824 {
825   TextureSet textures = TextureSet::New();
826
827   NativeImage nativeImage = NativeImage::DownCast( image );
828   if( nativeImage )
829   {
830     CreateNativeImageRenderer( nativeImage );
831     DALI_ASSERT_DEBUG( textures );
832     mImpl->mRenderer.SetTextures( textures );
833   }
834   else
835   {
836     // reuse existing code for regular images
837     CreateRenderer( textures ); // Textures will be retreived from Image
838   }
839   ApplyImageToSampler( image );
840 }
841
842 void ImageVisual::DoSetOnStage( Actor& actor )
843 {
844   if( mImageUrl.IsValid() )
845   {
846     InitializeRenderer();
847   }
848   else if( mImage )
849   {
850     InitializeRenderer( mImage );
851   }
852
853   if( !mImpl->mRenderer )
854   {
855     return;
856   }
857
858   mPlacementActor = actor;
859   // Search the Actor tree to find if Layer UI behaviour set.
860   Layer layer = actor.GetLayer();
861   if( layer && layer.GetBehavior() == Layer::LAYER_3D )
862   {
863      // Layer 3D set, do not align pixels
864      mImpl->mRenderer.RegisterProperty( PIXEL_ALIGNED_UNIFORM_NAME, PIXEL_ALIGN_OFF );
865   }
866
867   if( mPixelArea != FULL_TEXTURE_RECT )
868   {
869     mImpl->mRenderer.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, mPixelArea );
870   }
871
872   if( mLoading == false )
873   {
874     actor.AddRenderer( mImpl->mRenderer );
875     mPlacementActor.Reset();
876
877     // Image loaded and ready to display
878     ResourceReady( Toolkit::Visual::ResourceStatus::READY );
879   }
880 }
881
882 void ImageVisual::DoSetOffStage( Actor& actor )
883 {
884   // Visual::Base::SetOffStage only calls DoSetOffStage if mRenderer exists (is on onstage)
885
886   // Image release is dependent on the ReleasePolicy, renderer is destroyed.
887   actor.RemoveRenderer( mImpl->mRenderer);
888   if( mReleasePolicy == DevelImageVisual::ReleasePolicy::DETACHED )
889   {
890     RemoveTexture(); // If INVALID_TEXTURE_ID then removal will be attempted on atlas
891   }
892
893   if( mImageUrl.IsValid() )
894   {
895     // Legacy support for deprecated Dali::Image
896     mImage.Reset();
897   }
898   mLoading = false;
899   mImpl->mRenderer.Reset();
900   mPlacementActor.Reset();
901 }
902
903 void ImageVisual::DoCreatePropertyMap( Property::Map& map ) const
904 {
905   map.Clear();
906   map.Insert( Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE );
907
908   bool sync = IsSynchronousResourceLoading();
909   map.Insert( SYNCHRONOUS_LOADING, sync );
910   if( mImageUrl.IsValid() )
911   {
912     map.Insert( Toolkit::ImageVisual::Property::URL, mImageUrl.GetUrl() );
913     map.Insert( Toolkit::ImageVisual::Property::DESIRED_WIDTH, mDesiredSize.GetWidth() );
914     map.Insert( Toolkit::ImageVisual::Property::DESIRED_HEIGHT, mDesiredSize.GetHeight() );
915   }
916   else if( mImage )
917   {
918     map.Insert( Toolkit::ImageVisual::Property::DESIRED_WIDTH, static_cast<int>(mImage.GetWidth()) );
919     map.Insert( Toolkit::ImageVisual::Property::DESIRED_HEIGHT, static_cast<int>(mImage.GetHeight()) );
920
921     ResourceImage resourceImage = ResourceImage::DownCast(mImage);
922     if( resourceImage )
923     {
924       map.Insert( Toolkit::ImageVisual::Property::URL, resourceImage.GetUrl() );
925     }
926   }
927
928   map.Insert( Toolkit::ImageVisual::Property::FITTING_MODE, mFittingMode );
929   map.Insert( Toolkit::ImageVisual::Property::SAMPLING_MODE, mSamplingMode );
930
931   map.Insert( Toolkit::ImageVisual::Property::PIXEL_AREA, mPixelArea );
932   map.Insert( Toolkit::ImageVisual::Property::WRAP_MODE_U, mWrapModeU );
933   map.Insert( Toolkit::ImageVisual::Property::WRAP_MODE_V, mWrapModeV );
934
935   map.Insert( Toolkit::ImageVisual::Property::ATLASING, mAttemptAtlasing );
936
937   if( mMaskingData != NULL )
938   {
939     map.Insert( Toolkit::ImageVisual::Property::ALPHA_MASK_URL, mMaskingData->mAlphaMaskUrl.GetUrl() );
940     map.Insert( Toolkit::ImageVisual::Property::MASK_CONTENT_SCALE, mMaskingData->mContentScaleFactor );
941     map.Insert( Toolkit::ImageVisual::Property::CROP_TO_MASK, mMaskingData->mCropToMask );
942   }
943
944   map.Insert( Toolkit::DevelImageVisual::Property::LOAD_POLICY, mLoadPolicy );
945   map.Insert( Toolkit::DevelImageVisual::Property::RELEASE_POLICY, mReleasePolicy );
946   map.Insert( Toolkit::DevelImageVisual::Property::ORIENTATION_CORRECTION, mOrientationCorrection );
947 }
948
949 void ImageVisual::DoCreateInstancePropertyMap( Property::Map& map ) const
950 {
951   map.Clear();
952   map.Insert( Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE );
953   if( mImageUrl.IsValid() )
954   {
955     map.Insert( Toolkit::ImageVisual::Property::DESIRED_WIDTH, mDesiredSize.GetWidth() );
956     map.Insert( Toolkit::ImageVisual::Property::DESIRED_HEIGHT, mDesiredSize.GetHeight() );
957   }
958   else if( mImage )
959   {
960     map.Insert( Toolkit::ImageVisual::Property::DESIRED_WIDTH, static_cast<int>(mImage.GetWidth()) );
961     map.Insert( Toolkit::ImageVisual::Property::DESIRED_HEIGHT, static_cast<int>(mImage.GetHeight()) );
962   }
963 }
964
965 void ImageVisual::OnSetTransform()
966 {
967   if( mImpl->mRenderer )
968   {
969     mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
970   }
971 }
972
973 bool ImageVisual::IsResourceReady() const
974 {
975   return ( mImpl->mResourceStatus == Toolkit::Visual::ResourceStatus::READY ||
976            mImpl->mResourceStatus == Toolkit::Visual::ResourceStatus::FAILED );
977 }
978
979 Shader ImageVisual::GetImageShader( VisualFactoryCache& factoryCache, bool atlasing, bool defaultTextureWrapping )
980 {
981   Shader shader;
982   if( atlasing )
983   {
984     if( defaultTextureWrapping )
985     {
986       shader = factoryCache.GetShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP );
987       if( !shader )
988       {
989         shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_ATLAS_CLAMP );
990         shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
991         factoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP, shader );
992       }
993     }
994     else
995     {
996       shader = factoryCache.GetShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_CUSTOM_WRAP );
997       if( !shader )
998       {
999         shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_ATLAS_VARIOUS_WRAP );
1000         shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
1001         factoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_CUSTOM_WRAP, shader );
1002       }
1003     }
1004   }
1005   else
1006   {
1007     shader = factoryCache.GetShader( VisualFactoryCache::IMAGE_SHADER );
1008     if( !shader )
1009     {
1010       shader = DevelShader::New<uint32_t>(
1011         GraphicsGetBuiltinShader( "SHADER_IMAGE_VISUAL_SHADER_VERT" ),
1012         GraphicsGetBuiltinShader( "SHADER_IMAGE_VISUAL_NO_ATLAS_SHADER_FRAG" ),
1013         DevelShader::ShaderLanguage::SPIRV_1_0, Property::Map() );
1014
1015       //shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_NO_ATLAS );
1016       shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
1017       factoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER, shader );
1018     }
1019   }
1020
1021   return shader;
1022 }
1023
1024 void ImageVisual::ApplyImageToSampler( const Image& image )
1025 {
1026   if( image )
1027   {
1028     TextureSet textureSet = mImpl->mRenderer.GetTextures();
1029     DALI_ASSERT_DEBUG( textureSet ); // texture set should always exist by this time
1030
1031     TextureSetImage( textureSet, 0u, image );
1032     Sampler sampler = Sampler::New();
1033     sampler.SetWrapMode(  mWrapModeU, mWrapModeV  );
1034     textureSet.SetSampler( 0u, sampler );
1035   }
1036 }
1037
1038 // From existing atlas manager
1039 void ImageVisual::UploadCompleted()
1040 {
1041   // Texture has been uploaded. If weak handle is holding a placement actor, it is the time to add the renderer to actor.
1042   Actor actor = mPlacementActor.GetHandle();
1043   if( actor )
1044   {
1045     mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, mAtlasRect );
1046     actor.AddRenderer( mImpl->mRenderer );
1047     // reset the weak handle so that the renderer only get added to actor once
1048     mPlacementActor.Reset();
1049   }
1050   mLoading = false;
1051 }
1052
1053 // From Texture Manager
1054 void ImageVisual::UploadComplete( bool loadingSuccess, int32_t textureId, TextureSet textureSet, bool usingAtlas, const Vector4& atlasRectangle )
1055 {
1056   Toolkit::Visual::ResourceStatus resourceStatus;
1057   Actor actor = mPlacementActor.GetHandle();
1058   if( actor )
1059   {
1060     if( mImpl->mRenderer )
1061     {
1062       if( usingAtlas )
1063       {
1064         mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, mAtlasRect );
1065       }
1066
1067       actor.AddRenderer( mImpl->mRenderer );
1068       // reset the weak handle so that the renderer only get added to actor once
1069       mPlacementActor.Reset();
1070       if( loadingSuccess )
1071       {
1072         Sampler sampler = Sampler::New();
1073         sampler.SetWrapMode(  mWrapModeU, mWrapModeV  );
1074         textureSet.SetSampler( 0u, sampler );
1075         mImpl->mRenderer.SetTextures(textureSet);
1076
1077         resourceStatus = Toolkit::Visual::ResourceStatus::READY;
1078       }
1079       else
1080       {
1081         Image brokenImage = VisualFactoryCache::GetBrokenVisualImage();
1082
1083         textureSet = TextureSet::New();
1084         mImpl->mRenderer.SetTextures( textureSet );
1085
1086         ApplyImageToSampler( brokenImage );
1087
1088         resourceStatus = Toolkit::Visual::ResourceStatus::FAILED;
1089       }
1090       // Image loaded and ready to display
1091       ResourceReady( resourceStatus );
1092     }
1093   }
1094
1095   // Storing TextureSet needed when renderer staged.
1096   if( ! mImpl->mRenderer )
1097   {
1098     mTextures = textureSet;
1099   }
1100
1101   mLoading = false;
1102 }
1103
1104 void ImageVisual::RemoveTexture()
1105 {
1106   if( mTextureId != TextureManager::INVALID_TEXTURE_ID )
1107   {
1108     mFactoryCache.GetTextureManager().Remove( mTextureId );
1109     mTextureId = TextureManager::INVALID_TEXTURE_ID;
1110   }
1111   else
1112   {
1113     Vector4 atlasRect( 0.f, 0.f, 1.f, 1.f );
1114     Property::Index index = mImpl->mRenderer.GetPropertyIndex( ATLAS_RECT_UNIFORM_NAME );
1115     if( index != Property::INVALID_INDEX )
1116     {
1117       Property::Value atlasRectValue = mImpl->mRenderer.GetProperty( index );
1118       atlasRectValue.Get( atlasRect );
1119     }
1120
1121     TextureSet textureSet = mImpl->mRenderer.GetTextures();
1122     mImpl->mRenderer.Reset();
1123
1124     if( index != Property::INVALID_INDEX )
1125     {
1126       mFactoryCache.GetAtlasManager()->Remove( textureSet, atlasRect );
1127     }
1128   }
1129 }
1130
1131 } // namespace Internal
1132
1133 } // namespace Toolkit
1134
1135 } // namespace Dali