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