[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / npatch / npatch-visual.cpp
1 /*
2  * Copyright (c) 2024 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/npatch/npatch-visual.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/devel-api/adaptor-framework/image-loading.h>
23 #include <dali/devel-api/common/stage.h>
24 #include <dali/devel-api/rendering/renderer-devel.h>
25 #include <dali/integration-api/debug.h>
26
27 // INTERNAL INCLUDES
28 #include <dali-toolkit/devel-api/utility/npatch-helper.h>
29 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
30 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
31 #include <dali-toolkit/internal/visuals/image-atlas-manager.h>
32 #include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
33 #include <dali-toolkit/internal/visuals/image-visual-shader-feature-builder.h>
34 #include <dali-toolkit/internal/visuals/npatch-loader.h>
35 #include <dali-toolkit/internal/visuals/rendering-addon.h>
36 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
37 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
38 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
39 #include <dali-toolkit/internal/visuals/visual-factory-impl.h>
40 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
41 #include <dali-toolkit/public-api/visuals/visual-properties.h>
42
43 namespace Dali
44 {
45 namespace Toolkit
46 {
47 namespace Internal
48 {
49 namespace
50 {
51 const int CUSTOM_PROPERTY_COUNT(5); // fixed(3),stretch,aux
52 }
53
54 /////////////////NPatchVisual////////////////
55
56 NPatchVisualPtr NPatchVisual::New(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl, const Property::Map& properties)
57 {
58   NPatchVisualPtr nPatchVisual(new NPatchVisual(factoryCache, shaderFactory));
59   nPatchVisual->mImageUrl = imageUrl;
60   nPatchVisual->SetProperties(properties);
61   nPatchVisual->Initialize();
62   return nPatchVisual;
63 }
64
65 NPatchVisualPtr NPatchVisual::New(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl)
66 {
67   NPatchVisualPtr nPatchVisual(new NPatchVisual(factoryCache, shaderFactory));
68   nPatchVisual->mImageUrl = imageUrl;
69   nPatchVisual->Initialize();
70   return nPatchVisual;
71 }
72
73 void NPatchVisual::LoadImages()
74 {
75   TextureManager& textureManager     = mFactoryCache.GetTextureManager();
76   bool            synchronousLoading = mImpl->mFlags & Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
77
78   if(mId == NPatchData::INVALID_NPATCH_DATA_ID)
79   {
80     bool preMultiplyOnLoad = IsPreMultipliedAlphaEnabled() && !mImpl->mCustomShader ? true : false;
81     mId                    = mLoader.Load(textureManager, this, mImageUrl, mBorder, preMultiplyOnLoad, synchronousLoading);
82
83     NPatchDataPtr data;
84     if(mLoader.GetNPatchData(mId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
85     {
86       EnablePreMultipliedAlpha(data->IsPreMultiplied());
87     }
88   }
89
90   if(mAuxiliaryTextureId == TextureManager::INVALID_TEXTURE_ID && mAuxiliaryUrl.IsValid())
91   {
92     auto preMultiplyOnLoad = IsPreMultipliedAlphaEnabled() && !mImpl->mCustomShader
93                                ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD
94                                : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
95
96     TextureManager::MaskingDataPointer maskingDataPtr       = nullptr;
97     ImageAtlasManagerPtr               imageAtlasManagerPtr = nullptr;
98
99     bool atlasing      = false;
100     auto atlasRect     = Vector4::ZERO;
101     auto atlasRectSize = Dali::ImageDimensions();
102
103     bool loadingStatus = false;
104
105     // Load the auxiliary image
106     mAuxiliaryTextureSet = textureManager.LoadTexture(mAuxiliaryUrl, Dali::ImageDimensions(), FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, maskingDataPtr, synchronousLoading, mAuxiliaryTextureId, atlasRect, atlasRectSize, atlasing, loadingStatus, this, nullptr, imageAtlasManagerPtr, true, TextureManager::ReloadPolicy::CACHED, preMultiplyOnLoad);
107
108     if(mAuxiliaryTextureSet)
109     {
110       Sampler sampler = Sampler::New();
111       sampler.SetWrapMode(WrapMode::DEFAULT, WrapMode::DEFAULT);
112       mAuxiliaryTextureSet.SetSampler(0u, sampler);
113     }
114
115     // If synchronousLoading is true, we can check the auxiliaryResource's status now.
116     if(synchronousLoading)
117     {
118       mAuxiliaryResourceStatus = (mAuxiliaryTextureSet && mAuxiliaryTextureSet.GetTextureCount() > 0u) ? Toolkit::Visual::ResourceStatus::READY : Toolkit::Visual::ResourceStatus::FAILED;
119     }
120   }
121 }
122
123 void NPatchVisual::GetNaturalSize(Vector2& naturalSize)
124 {
125   naturalSize.x = 0u;
126   naturalSize.y = 0u;
127
128   // load now if not already loaded
129   NPatchDataPtr data;
130   if(mLoader.GetNPatchData(mId, data) && data->GetLoadingState() != NPatchData::LoadingState::LOADING)
131   {
132     naturalSize.x = data->GetCroppedWidth();
133     naturalSize.y = data->GetCroppedHeight();
134   }
135   else
136   {
137     if(mImageUrl.IsValid())
138     {
139       ImageDimensions dimensions = Dali::GetOriginalImageSize(mImageUrl.GetUrl());
140       if(dimensions != ImageDimensions(0, 0))
141       {
142         naturalSize.x = dimensions.GetWidth();
143         naturalSize.y = dimensions.GetHeight();
144       }
145     }
146   }
147
148   if(mAuxiliaryTextureSet && mAuxiliaryTextureSet.GetTextureCount() > 0u)
149   {
150     naturalSize.x = std::max(naturalSize.x, float(mAuxiliaryTextureSet.GetTexture(0u).GetWidth()));
151     naturalSize.y = std::max(naturalSize.y, float(mAuxiliaryTextureSet.GetTexture(0u).GetHeight()));
152   }
153 }
154
155 void NPatchVisual::DoSetProperties(const Property::Map& propertyMap)
156 {
157   // URL is already passed in via constructor
158
159   Property::Value* borderOnlyValue = propertyMap.Find(Toolkit::ImageVisual::Property::BORDER_ONLY, BORDER_ONLY);
160   if(borderOnlyValue)
161   {
162     borderOnlyValue->Get(mBorderOnly);
163   }
164
165   Property::Value* borderValue = propertyMap.Find(Toolkit::ImageVisual::Property::BORDER, BORDER);
166   if(borderValue && !borderValue->Get(mBorder)) // If value exists and is rect, just set mBorder
167   {
168     // Not a rect so try vector4
169     Vector4 border;
170     if(borderValue->Get(border))
171     {
172       mBorder.left   = static_cast<int>(border.x);
173       mBorder.right  = static_cast<int>(border.y);
174       mBorder.bottom = static_cast<int>(border.z);
175       mBorder.top    = static_cast<int>(border.w);
176     }
177   }
178
179   Property::Value* auxImage = propertyMap.Find(Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE, AUXILIARY_IMAGE_NAME);
180   if(auxImage)
181   {
182     std::string url;
183     if(auxImage->Get(url))
184     {
185       mAuxiliaryUrl = url;
186     }
187   }
188
189   Property::Value* auxImageAlpha = propertyMap.Find(Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE_ALPHA, AUXILIARY_IMAGE_ALPHA_NAME);
190   if(auxImageAlpha)
191   {
192     auxImageAlpha->Get(mAuxiliaryImageAlpha);
193   }
194
195   Property::Value* synchronousLoading = propertyMap.Find(Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING, SYNCHRONOUS_LOADING);
196   if(synchronousLoading)
197   {
198     bool sync = false;
199     synchronousLoading->Get(sync);
200     if(sync)
201     {
202       mImpl->mFlags |= Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
203     }
204     else
205     {
206       mImpl->mFlags &= ~Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
207     }
208   }
209
210   Property::Value* releasePolicy = propertyMap.Find(Toolkit::ImageVisual::Property::RELEASE_POLICY, RELEASE_POLICY_NAME);
211   if(releasePolicy)
212   {
213     releasePolicy->Get(mReleasePolicy);
214   }
215 }
216
217 void NPatchVisual::DoSetOnScene(Actor& actor)
218 {
219   // load when first go on stage
220   LoadImages();
221
222   // Set mPlacementActor now, because some case, LoadImages can use this information in LoadComplete API.
223   // at this case, we try to SetResouce to mPlaceActor twice. so, we should avoid that case.
224   mPlacementActor = actor;
225
226   NPatchDataPtr data;
227   if(mImpl->mRenderer && mLoader.GetNPatchData(mId, data) && data->GetLoadingState() != NPatchData::LoadingState::LOADING)
228   {
229     // If mAuxiliaryUrl need to be loaded, we should wait it until LoadComplete called.
230     if(!mAuxiliaryUrl.IsValid() || mAuxiliaryResourceStatus != Toolkit::Visual::ResourceStatus::PREPARING)
231     {
232       SetResource();
233     }
234   }
235 }
236
237 void NPatchVisual::DoSetOffScene(Actor& actor)
238 {
239   if(mReleasePolicy == Toolkit::ImageVisual::ReleasePolicy::DETACHED)
240   {
241     if(mId != NPatchData::INVALID_NPATCH_DATA_ID)
242     {
243       mLoader.RequestRemove(mId, this);
244       mImpl->mResourceStatus = Toolkit::Visual::ResourceStatus::PREPARING;
245       mId                    = NPatchData::INVALID_NPATCH_DATA_ID;
246     }
247     if(mAuxiliaryTextureId != TextureManager::INVALID_TEXTURE_ID)
248     {
249       TextureManager& textureManager = mFactoryCache.GetTextureManager();
250       textureManager.RequestRemove(mAuxiliaryTextureId, this);
251       mAuxiliaryTextureId      = TextureManager::INVALID_TEXTURE_ID;
252       mAuxiliaryResourceStatus = Toolkit::Visual::ResourceStatus::PREPARING;
253       mAuxiliaryTextureSet.Reset();
254     }
255   }
256
257   actor.RemoveRenderer(mImpl->mRenderer);
258   mPlacementActor.Reset();
259 }
260
261 void NPatchVisual::OnSetTransform()
262 {
263   if(mImpl->mRenderer)
264   {
265     mImpl->mTransform.SetUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
266   }
267 }
268
269 void NPatchVisual::DoCreatePropertyMap(Property::Map& map) const
270 {
271   map.Clear();
272   bool sync = IsSynchronousLoadingRequired();
273   map.Insert(Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING, sync);
274   map.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::N_PATCH);
275   map.Insert(Toolkit::ImageVisual::Property::URL, mImageUrl.GetUrl());
276   map.Insert(Toolkit::ImageVisual::Property::BORDER_ONLY, mBorderOnly);
277   map.Insert(Toolkit::ImageVisual::Property::BORDER, mBorder);
278   map.Insert(Toolkit::ImageVisual::Property::RELEASE_POLICY, mReleasePolicy);
279
280   if(mAuxiliaryUrl.IsValid())
281   {
282     map.Insert(Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE, mAuxiliaryUrl.GetUrl());
283     map.Insert(Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE_ALPHA, mAuxiliaryImageAlpha);
284   }
285 }
286
287 void NPatchVisual::DoCreateInstancePropertyMap(Property::Map& map) const
288 {
289   if(mAuxiliaryUrl.IsValid())
290   {
291     map.Insert(Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE, mAuxiliaryUrl.GetUrl());
292     map.Insert(Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE_ALPHA, mAuxiliaryImageAlpha);
293   }
294 }
295
296 NPatchVisual::NPatchVisual(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory)
297 : Visual::Base(factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::N_PATCH),
298   mPlacementActor(),
299   mLoader(factoryCache.GetNPatchLoader()),
300   mImageVisualShaderFactory(shaderFactory),
301   mImageUrl(),
302   mAuxiliaryUrl(),
303   mId(NPatchData::INVALID_NPATCH_DATA_ID),
304   mAuxiliaryTextureSet(),
305   mAuxiliaryTextureId(TextureManager::INVALID_TEXTURE_ID),
306   mAuxiliaryResourceStatus(Toolkit::Visual::ResourceStatus::PREPARING),
307   mBorderOnly(false),
308   mBorder(),
309   mAuxiliaryImageAlpha(0.0f),
310   mReleasePolicy(Toolkit::ImageVisual::ReleasePolicy::DETACHED)
311 {
312   EnablePreMultipliedAlpha(mFactoryCache.GetPreMultiplyOnLoad());
313 }
314
315 NPatchVisual::~NPatchVisual()
316 {
317   if(Stage::IsInstalled())
318   {
319     if(mReleasePolicy != Toolkit::ImageVisual::ReleasePolicy::NEVER)
320     {
321       if(mId != NPatchData::INVALID_NPATCH_DATA_ID)
322       {
323         mLoader.RequestRemove(mId, this);
324         mId = NPatchData::INVALID_NPATCH_DATA_ID;
325       }
326       if(mAuxiliaryTextureId != TextureManager::INVALID_TEXTURE_ID)
327       {
328         TextureManager& textureManager = mFactoryCache.GetTextureManager();
329
330         textureManager.RequestRemove(mAuxiliaryTextureId, this);
331         mAuxiliaryTextureId = TextureManager::INVALID_TEXTURE_ID;
332         mAuxiliaryTextureSet.Reset();
333       }
334     }
335   }
336 }
337
338 void NPatchVisual::OnInitialize()
339 {
340   // Get basic geometry and shader
341   Geometry geometry                        = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY);
342   auto     imageVisualShaderFeatureBuilder = ImageVisualShaderFeatureBuilder();
343   Shader   shader                          = mImageVisualShaderFactory.GetShader(
344     mFactoryCache,
345     imageVisualShaderFeatureBuilder);
346
347   mImpl->mRenderer = VisualRenderer::New(geometry, shader);
348   mImpl->mRenderer.ReserveCustomProperties(CUSTOM_PROPERTY_COUNT);
349
350   //Register transform properties
351   mImpl->mTransform.SetUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
352 }
353
354 Geometry NPatchVisual::CreateGeometry()
355 {
356   Geometry      geometry;
357   NPatchDataPtr data;
358   if(mLoader.GetNPatchData(mId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
359   {
360     if(data->GetStretchPixelsX().Size() == 1 && data->GetStretchPixelsY().Size() == 1)
361     {
362       if(DALI_UNLIKELY(mBorderOnly))
363       {
364         geometry = GetNinePatchGeometry(VisualFactoryCache::NINE_PATCH_BORDER_GEOMETRY);
365       }
366       else
367       {
368         if(data->GetRenderingMap())
369         {
370           uint32_t elementCount[2];
371           geometry = RenderingAddOn::Get().CreateGeometryGrid(data->GetRenderingMap(), Uint16Pair(3, 3), elementCount);
372           if(mImpl->mRenderer)
373           {
374             RenderingAddOn::Get().SubmitRenderTask(mImpl->mRenderer, data->GetRenderingMap());
375           }
376         }
377         else
378         {
379           geometry = GetNinePatchGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY);
380         }
381       }
382     }
383     else if(data->GetStretchPixelsX().Size() > 0 || data->GetStretchPixelsY().Size() > 0)
384     {
385       Uint16Pair gridSize(2 * data->GetStretchPixelsX().Size() + 1, 2 * data->GetStretchPixelsY().Size() + 1);
386       if(!data->GetRenderingMap())
387       {
388         geometry = !mBorderOnly ? NPatchHelper::CreateGridGeometry(gridSize) : NPatchHelper::CreateBorderGeometry(gridSize);
389       }
390       else
391       {
392         uint32_t elementCount[2];
393         geometry = !mBorderOnly ? RenderingAddOn::Get().CreateGeometryGrid(data->GetRenderingMap(), gridSize, elementCount) : NPatchHelper::CreateBorderGeometry(gridSize);
394         if(mImpl->mRenderer)
395         {
396           RenderingAddOn::Get().SubmitRenderTask(mImpl->mRenderer, data->GetRenderingMap());
397         }
398       }
399     }
400   }
401   else
402   {
403     // no N patch data so use default geometry
404     geometry = GetNinePatchGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY);
405   }
406   return geometry;
407 }
408
409 Shader NPatchVisual::CreateShader()
410 {
411   Shader        shader;
412   NPatchDataPtr data;
413   // 0 is either no data (load failed?) or no stretch regions on image
414   // for both cases we use the default shader
415   NPatchUtility::StretchRanges::SizeType xStretchCount = 0;
416   NPatchUtility::StretchRanges::SizeType yStretchCount = 0;
417
418   auto fragmentShader = mAuxiliaryResourceStatus == Toolkit::Visual::ResourceStatus::READY ? SHADER_NPATCH_VISUAL_MASK_SHADER_FRAG
419                                                                                            : SHADER_NPATCH_VISUAL_SHADER_FRAG;
420   auto shaderType     = mAuxiliaryResourceStatus == Toolkit::Visual::ResourceStatus::READY ? VisualFactoryCache::NINE_PATCH_MASK_SHADER
421                                                                                            : VisualFactoryCache::NINE_PATCH_SHADER;
422
423   // ask loader for the regions
424   if(mLoader.GetNPatchData(mId, data))
425   {
426     xStretchCount = data->GetStretchPixelsX().Count();
427     yStretchCount = data->GetStretchPixelsY().Count();
428   }
429
430   if(DALI_LIKELY(!mImpl->mCustomShader))
431   {
432     if(DALI_LIKELY((xStretchCount == 1 && yStretchCount == 1) ||
433                    (xStretchCount == 0 && yStretchCount == 0)))
434     {
435       shader = mFactoryCache.GetShader(shaderType);
436       if(DALI_UNLIKELY(!shader))
437       {
438         shader = mFactoryCache.GenerateAndSaveShader(shaderType, SHADER_NPATCH_VISUAL_3X3_SHADER_VERT, fragmentShader);
439       }
440     }
441     else if(xStretchCount > 0 || yStretchCount > 0)
442     {
443       std::stringstream shaderName;
444       shaderName << "N_PATCH_" << xStretchCount << "x" << yStretchCount;
445
446       std::stringstream vertexShader;
447       vertexShader << "#define FACTOR_SIZE_X " << xStretchCount + 2 << "\n"
448                    << "#define FACTOR_SIZE_Y " << yStretchCount + 2 << "\n"
449                    << SHADER_NPATCH_VISUAL_SHADER_VERT;
450
451       shader = Shader::New(vertexShader.str(), fragmentShader, Dali::Shader::Hint::NONE, shaderName.str());
452     }
453   }
454   else
455   {
456     Dali::Shader::Hint::Value hints = Dali::Shader::Hint::NONE;
457
458     if(!mImpl->mCustomShader->mFragmentShader.empty())
459     {
460       fragmentShader = mImpl->mCustomShader->mFragmentShader.c_str();
461     }
462     hints = mImpl->mCustomShader->mHints;
463
464     /* Apply Custom Vertex Shader only if image is 9-patch */
465     if((xStretchCount == 1 && yStretchCount == 1) ||
466        (xStretchCount == 0 && yStretchCount == 0))
467     {
468       const char* vertexShader = SHADER_NPATCH_VISUAL_3X3_SHADER_VERT.data();
469
470       if(!mImpl->mCustomShader->mVertexShader.empty())
471       {
472         vertexShader = mImpl->mCustomShader->mVertexShader.c_str();
473       }
474       shader = Shader::New(vertexShader, fragmentShader, hints);
475     }
476     else if(xStretchCount > 0 || yStretchCount > 0)
477     {
478       std::stringstream shaderName;
479       shaderName << "N_PATCH_" << xStretchCount << "x" << yStretchCount;
480
481       std::stringstream vertexShader;
482       vertexShader << "#define FACTOR_SIZE_X " << xStretchCount + 2 << "\n"
483                    << "#define FACTOR_SIZE_Y " << yStretchCount + 2 << "\n"
484                    << SHADER_NPATCH_VISUAL_SHADER_VERT;
485
486       shader = Shader::New(vertexShader.str(), fragmentShader, hints, shaderName.str());
487     }
488   }
489
490   return shader;
491 }
492
493 void NPatchVisual::ApplyTextureAndUniforms()
494 {
495   NPatchDataPtr data;
496   TextureSet    textureSet;
497
498   if(mLoader.GetNPatchData(mId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
499   {
500     textureSet = data->GetTextures();
501     NPatchHelper::ApplyTextureAndUniforms(mImpl->mRenderer, data.Get());
502
503     if(mAuxiliaryResourceStatus == Toolkit::Visual::ResourceStatus::READY)
504     {
505       DALI_ASSERT_ALWAYS(mAuxiliaryTextureId != TextureManager::INVALID_TEXTURE_ID);
506       DALI_ASSERT_ALWAYS(mAuxiliaryTextureSet && mAuxiliaryTextureSet.GetTextureCount() > 0u);
507
508       // TODO : This code exist due to the texture cache manager hold TextureSet, not Texture.
509       // If we call textureSet.SetTexture(1, texture) directly, the cached TextureSet also be changed.
510       // We should make pass utc-Dali-VisualFactory.cpp UtcDaliNPatchVisualAuxiliaryImage02().
511       TextureSet tempTextureSet = TextureSet::New();
512       tempTextureSet.SetTexture(1, mAuxiliaryTextureSet.GetTexture(0));
513       tempTextureSet.SetTexture(0, textureSet.GetTexture(0));
514       textureSet = tempTextureSet;
515
516       mImpl->mRenderer.RegisterProperty(DevelImageVisual::Property::AUXILIARY_IMAGE_ALPHA,
517                                         AUXILIARY_IMAGE_ALPHA_NAME,
518                                         mAuxiliaryImageAlpha);
519     }
520     mImpl->mRenderer.SetTextures(textureSet);
521   }
522   else
523   {
524     DALI_LOG_ERROR("The N patch image '%s' is not a valid N patch image\n", mImageUrl.GetUrl().c_str());
525     Actor   actor     = mPlacementActor.GetHandle();
526     Vector2 imageSize = Vector2::ZERO;
527     if(actor)
528     {
529       imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
530     }
531     mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize, false);
532   }
533
534   // Register transform properties
535   mImpl->mTransform.SetUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
536 }
537
538 Geometry NPatchVisual::GetNinePatchGeometry(VisualFactoryCache::GeometryType subType)
539 {
540   Geometry geometry = mFactoryCache.GetGeometry(subType);
541   if(!geometry)
542   {
543     if(DALI_LIKELY(VisualFactoryCache::NINE_PATCH_GEOMETRY == subType))
544     {
545       geometry = NPatchHelper::CreateGridGeometry(Uint16Pair(3, 3));
546     }
547     else if(VisualFactoryCache::NINE_PATCH_BORDER_GEOMETRY == subType)
548     {
549       geometry = NPatchHelper::CreateBorderGeometry(Uint16Pair(3, 3));
550     }
551     mFactoryCache.SaveGeometry(subType, geometry);
552   }
553   return geometry;
554 }
555
556 void NPatchVisual::SetResource()
557 {
558   NPatchDataPtr data;
559   if(mImpl->mRenderer && mLoader.GetNPatchData(mId, data))
560   {
561     Geometry geometry = CreateGeometry();
562     Shader   shader   = CreateShader();
563
564     mImpl->mRenderer.SetGeometry(geometry);
565     mImpl->mRenderer.SetShader(shader);
566
567     if(RenderingAddOn::Get().IsValid())
568     {
569       RenderingAddOn::Get().SubmitRenderTask(mImpl->mRenderer, data->GetRenderingMap());
570     }
571     Actor actor = mPlacementActor.GetHandle();
572     if(actor)
573     {
574       ApplyTextureAndUniforms();
575       actor.AddRenderer(mImpl->mRenderer);
576       mPlacementActor.Reset();
577     }
578
579     // npatch loaded and ready to display
580     if(data->GetLoadingState() != NPatchData::LoadingState::LOAD_COMPLETE)
581     {
582       ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
583     }
584     else
585     {
586       ResourceReady(Toolkit::Visual::ResourceStatus::READY);
587     }
588   }
589 }
590
591 void NPatchVisual::LoadComplete(bool loadSuccess, TextureInformation textureInformation)
592 {
593   if(textureInformation.url.length() > 0) // For the Url.
594   {
595     if(DALI_UNLIKELY(mId == NPatchData::INVALID_NPATCH_DATA_ID))
596     {
597       // Special case when mLoader.Load call LoadComplete function before mId setup.
598       // We can overwrite mId.
599       mId = static_cast<NPatchData::NPatchDataId>(textureInformation.textureId);
600     }
601     if(loadSuccess)
602     {
603       EnablePreMultipliedAlpha(textureInformation.preMultiplied);
604     }
605   }
606   else // For the AuxiliaryUrl
607   {
608     if(DALI_UNLIKELY(mAuxiliaryTextureId == TextureManager::INVALID_TEXTURE_ID))
609     {
610       // Special case when TextureManager.LoadTexture call LoadComplete function before mAuxiliaryTextureId setup.
611       // We can overwrite mAuxiliaryTextureId.
612       mAuxiliaryTextureId = textureInformation.textureId;
613     }
614     if(loadSuccess)
615     {
616       mAuxiliaryTextureSet = textureInformation.textureSet;
617       if(mAuxiliaryTextureSet)
618       {
619         Sampler sampler = Sampler::New();
620         sampler.SetWrapMode(WrapMode::DEFAULT, WrapMode::DEFAULT);
621         mAuxiliaryTextureSet.SetSampler(0u, sampler);
622       }
623
624       mAuxiliaryResourceStatus = Toolkit::Visual::ResourceStatus::READY;
625     }
626     else
627     {
628       mAuxiliaryResourceStatus = Toolkit::Visual::ResourceStatus::FAILED;
629     }
630   }
631
632   // If auxiliaryUrl didn't required OR auxiliaryUrl load done.
633   if(!mAuxiliaryUrl.IsValid() || mAuxiliaryResourceStatus != Toolkit::Visual::ResourceStatus::PREPARING)
634   {
635     NPatchDataPtr data;
636     // and.. If Url loading done.
637     if(mImpl->mRenderer && mLoader.GetNPatchData(mId, data) && data->GetLoadingState() != NPatchData::LoadingState::LOADING)
638     {
639       SetResource();
640     }
641   }
642 }
643
644 } // namespace Internal
645
646 } // namespace Toolkit
647
648 } // namespace Dali