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