Merge "Do not clear keyboard focus on touch when alwaysShowFocus is true." into devel...
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / texture-manager-impl.h
1 #ifndef DALI_TOOLKIT_TEXTURE_MANAGER_IMPL_H
2 #define DALI_TOOLKIT_TEXTURE_MANAGER_IMPL_H
3
4 /*
5  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 // EXTERNAL INCLUDES
21 #include <deque>
22 #include <functional>
23 #include <string>
24 #include <dali/public-api/common/dali-vector.h>
25 #include <dali/public-api/object/ref-object.h>
26 #include <dali/public-api/rendering/texture-set.h>
27 #include <dali/devel-api/common/owner-container.h>
28 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
29
30 // INTERNAL INCLUDES
31 #include <dali-toolkit/devel-api/image-loader/async-image-loader-devel.h>
32 #include <dali-toolkit/devel-api/image-loader/image-atlas.h>
33 #include <dali-toolkit/public-api/image-loader/async-image-loader.h>
34 #include <dali-toolkit/internal/visuals/texture-upload-observer.h>
35 #include <dali-toolkit/internal/visuals/visual-url.h>
36 #include <dali-toolkit/internal/helpers/round-robin-container-view.h>
37 #include <dali-toolkit/internal/image-loader/async-image-loader-impl.h>
38
39
40 namespace Dali
41 {
42
43 namespace Toolkit
44 {
45
46 namespace Internal
47 {
48
49 /**
50  * The TextureManager provides a common Image loading API for Visuals.
51  *
52  * The TextureManager is responsible for providing sync, async, atlased and non-atlased loads.
53  * Texture caching is provided and performed when possible.
54  * Broken Images are automatically provided on load failure.
55  */
56 class TextureManager : public ConnectionTracker
57 {
58 public:
59
60   typedef int32_t TextureId;       ///< The TextureId type. This is used as a handle to refer to a particular Texture.
61   static const int INVALID_TEXTURE_ID = -1; ///< Used to represent a null TextureId or error
62
63   /**
64    * Whether the texture should be atlased or uploaded into it's own GPU texture
65    */
66   enum UseAtlas
67   {
68     NO_ATLAS,
69     USE_ATLAS
70   };
71
72   /**
73    * Whether the pixel data should be kept in TextureManager, or uploaded for rendering
74    */
75   enum StorageType
76   {
77     KEEP_PIXEL_BUFFER,
78     UPLOAD_TO_TEXTURE
79   };
80
81   /**
82    * Whether the texture should be loaded synchronously or asynchronously.
83    */
84   enum LoadType
85   {
86     LOAD_ASYNCHRONOUSLY,
87     LOAD_SYNCHRONOUSLY
88   };
89
90   /**
91    * @brief The LoadState Enumeration represents the current state of a particular Texture's life-cycle.
92    */
93   enum LoadState
94   {
95     NOT_STARTED,     ///< Default
96     LOADING,         ///< Loading has been started, but not finished.
97     LOAD_FINISHED,   ///< Loading has finished. (for CPU storage only)
98     WAITING_FOR_MASK,///< Loading has finished, but waiting for mask image
99     UPLOADED,        ///< Uploaded and ready. (For GPU upload only)
100     CANCELLED,       ///< Removed before loading completed
101     LOAD_FAILED      ///< Async loading failed, e.g. connection problem
102   };
103
104 public:
105
106   /**
107    * Constructor.
108    */
109   TextureManager();
110
111   /**
112    * Destructor.
113    */
114   ~TextureManager();
115
116
117   // TextureManager Main API:
118
119   /**
120    * @brief Requests an image load of the given URL.
121    *
122    * The parameters are used to specify how the image is loaded.
123    * The observer has the UploadComplete method called when the load is ready.
124    *
125    * When the client has finished with the Texture, Remove() should be called.
126    *
127    * @param[in] url               The URL of the image to load
128    * @param[in] desiredSize       The size the image is likely to appear at. This can be set to 0,0 for automatic
129    * @param[in] fittingMode       The FittingMode to use
130    * @param[in] samplingMode      The SamplingMode to use
131    * @param[in] useAtlasing       Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be loaded, and marked successful,
132    *                              but "useAtlasing" will be set to false in the "UploadCompleted" callback from the TextureManagerUploadObserver.
133    * @param[in] observer          The client object should inherit from this and provide the "UploadCompleted" virtual.
134    *                              This is called when an image load completes (or fails).
135    * @return                      A TextureId to use as a handle to reference this Texture
136    */
137   TextureId RequestLoad( const VisualUrl&         url,
138                          const ImageDimensions    desiredSize,
139                          FittingMode::Type        fittingMode,
140                          Dali::SamplingMode::Type samplingMode,
141                          const UseAtlas           useAtlasing,
142                          TextureUploadObserver*   observer );
143
144   /**
145    * @brief Requests an image load of the given URL, when the texture has
146    * have loaded, it will perform a blend with the image mask, and upload
147    * the blended texture.
148    *
149    * The parameters are used to specify how the image is loaded.
150    * The observer has the UploadComplete method called when the load is ready.
151    *
152    * When the client has finished with the Texture, Remove() should be called.
153    *
154    * @param[in] url               The URL of the image to load
155    * @param[in] maskTextureId     The texture id of an image to mask this with (can be INVALID if no masking required)
156    * @param[in] contentScale      The scale factor to apply to the image before masking
157    * @param[in] desiredSize       The size the image is likely to appear at. This can be set to 0,0 for automatic
158    * @param[in] fittingMode       The FittingMode to use
159    * @param[in] samplingMode      The SamplingMode to use
160    * @param[in] useAtlasing       Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be loaded, and marked successful,
161    *                              but "useAtlasing" will be set to false in the "UploadCompleted" callback from the TextureManagerUploadObserver.
162    * @param[in] cropToMask        Only used with masking, this will crop the scaled image to the mask size. If false, then the mask will be scaled to fit the image before being applied.
163    * @param[in] observer          The client object should inherit from this and provide the "UploadCompleted" virtual.
164    *                              This is called when an image load completes (or fails).
165    * @return                      A TextureId to use as a handle to reference this Texture
166    */
167   TextureId RequestLoad( const VisualUrl&         url,
168                          TextureId                maskTextureId,
169                          float                    contentScale,
170                          const ImageDimensions    desiredSize,
171                          FittingMode::Type        fittingMode,
172                          Dali::SamplingMode::Type samplingMode,
173                          const UseAtlas           useAtlasing,
174                          bool                     cropToMask,
175                          TextureUploadObserver*   observer );
176
177   /**
178    * Requests a masking image to be loaded. This mask is not uploaded to GL,
179    * instead, it is stored in CPU memory, and can be used for CPU blending.
180    */
181   TextureId RequestMaskLoad( const VisualUrl& maskUrl );
182
183   /**
184    * @brief Remove a Texture from the TextureManager.
185    *
186    * Textures are cached and therefore only the removal of the last
187    * occurrence of a Texture will cause its removal internally.
188    *
189    * @param[in] textureId The ID of the Texture to remove.
190    */
191   void Remove( const TextureManager::TextureId textureId );
192
193   /**
194    * Get the visualUrl associated with the texture id
195    */
196   const VisualUrl& GetVisualUrl( TextureId textureId );
197
198   /**
199    * @brief Get the current state of a texture
200    * @param[in] textureId The texture id to query
201    * @return The loading state if the texture is valid, or NOT_STARTED if the textureId
202    * is not valid.
203    */
204   LoadState GetTextureState( TextureId textureId );
205
206   /**
207    * @brief Get the associated texture set if the texture id is valid
208    * @param[in] textureId The texture Id to look up
209    * @return the associated texture set, or an empty handle if textureId is not valid
210    */
211   TextureSet GetTextureSet( TextureId textureId );
212
213   /**
214    * Adds an external texture to the texture manager
215    * @param[in] texture The texture to add
216    * @return string containing the URL for the texture
217    */
218   std::string AddExternalTexture( TextureSet& texture );
219
220   /**
221    * Removes an external texture from texture manager
222    * @param[in] url The string containing the texture to remove
223    * @return handle to the texture
224    */
225   TextureSet RemoveExternalTexture( const std::string& url );
226
227 private:
228
229   /**
230    * @brief Requests an image load of the given URL, when the texture has
231    * have loaded, if there is a valid maskTextureId, it will perform a
232    * CPU blend with the mask, and upload the blend texture.
233    *
234    * The parameters are used to specify how the image is loaded.
235    * The observer has the UploadComplete method called when the load is ready.
236    *
237    * When the client has finished with the Texture, Remove() should be called.
238    *
239    * @param[in] url               The URL of the image to load
240    * @param[in] maskTextureId     The texture id of an image to use as a mask. If no mask is required, then set to INVALID_TEXTURE_ID
241    * @param[in] contentScale      The scaling factor to apply to the content when masking
242    * @param[in] desiredSize       The size the image is likely to appear at. This can be set to 0,0 for automatic
243    * @param[in] fittingMode       The FittingMode to use
244    * @param[in] samplingMode      The SamplingMode to use
245    * @param[in] useAtlasing       Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be loaded, and marked successful,
246    *                              but "useAtlasing" will be set to false in the "UploadCompleted" callback from the TextureManagerUploadObserver.
247    * @param[in] cropToMask        Whether to crop the target after masking, or scale the mask to the image before masking.
248    * @param[in] storageType,      Whether the pixel data is stored in the cache or uploaded to the GPU
249    * @param[in] observer          The client object should inherit from this and provide the "UploadCompleted" virtual.
250    *                              This is called when an image load completes (or fails).
251    * @return                      A TextureId to use as a handle to reference this Texture
252    */
253   TextureId RequestLoadInternal(
254     const VisualUrl&         url,
255     TextureId                maskTextureId,
256     float                    contentScale,
257     const ImageDimensions    desiredSize,
258     FittingMode::Type        fittingMode,
259     Dali::SamplingMode::Type samplingMode,
260     UseAtlas                 useAtlas,
261     bool                     cropToMask,
262     StorageType              storageType,
263     TextureUploadObserver*   observer );
264
265
266   typedef size_t TextureHash; ///< The type used to store the hash used for Texture caching.
267
268   /**
269    * @brief This struct is used to manage the life-cycle of Texture loading and caching.
270    */
271   struct TextureInfo
272   {
273     TextureInfo( TextureId textureId,
274                  TextureId maskTextureId,
275                  const VisualUrl& url,
276                  ImageDimensions desiredSize,
277                  float scaleFactor,
278                  FittingMode::Type fittingMode,
279                  Dali::SamplingMode::Type samplingMode,
280                  bool loadSynchronously,
281                  bool cropToMask,
282                  UseAtlas useAtlas,
283                  TextureManager::TextureHash hash )
284     : url( url ),
285       desiredSize( desiredSize ),
286       useSize( desiredSize ),
287       atlasRect( 0.0f, 0.0f, 1.0f, 1.0f ), // Full atlas rectangle
288       textureId( textureId ),
289       maskTextureId( maskTextureId ),
290       hash( hash ),
291       scaleFactor( scaleFactor ),
292       referenceCount( 1u ),
293       loadState( NOT_STARTED ),
294       fittingMode( fittingMode ),
295       samplingMode( samplingMode ),
296       storageType( UPLOAD_TO_TEXTURE ),
297       loadSynchronously( loadSynchronously ),
298       useAtlas( useAtlas ),
299       cropToMask( cropToMask )
300     {
301     }
302
303     /**
304      * Container type used to store all observer clients of this Texture
305      */
306     typedef Dali::Vector< TextureUploadObserver* > ObserverListType;
307
308     ObserverListType observerList; ///< Container used to store all observer clients of this Texture
309     Toolkit::ImageAtlas atlas;     ///< The atlas this Texture lays within (if any)
310     Devel::PixelBuffer pixelBuffer;///< The PixelBuffer holding the image data (May be empty after upload)
311     TextureSet textureSet;         ///< The TextureSet holding the Texture
312     VisualUrl url;                 ///< The URL of the image
313     ImageDimensions desiredSize;   ///< The size requested
314     ImageDimensions useSize;       ///< The size used
315     Vector4 atlasRect;             ///< The atlas rect used if atlased
316     TextureId textureId;           ///< The TextureId associated with this Texture
317     TextureId maskTextureId;       ///< The mask TextureId to be applied on load
318     TextureManager::TextureHash hash; ///< The hash used to cache this Texture
319     float scaleFactor;             ///< The scale factor to apply to the Texture when masking
320     int16_t referenceCount;        ///< The reference count of clients using this Texture
321     LoadState loadState:3;         ///< The load state showing the load progress of the Texture
322     FittingMode::Type fittingMode:2; ///< The requested FittingMode
323     Dali::SamplingMode::Type samplingMode:3; ///< The requested SamplingMode
324     StorageType storageType:1;     ///< CPU storage / GPU upload;
325     bool loadSynchronously:1;      ///< True if synchronous loading was requested
326     UseAtlas useAtlas:1;           ///< USE_ATLAS if an atlas was requested. This is updated to false if atlas is not used
327     bool cropToMask:1;             ///< true if the image should be cropped to the mask size.
328   };
329
330   // Structs:
331
332   /**
333    * Struct to hold information about a requested Async load.
334    * This is used to look up a TextureManager::TextureId from the returned AsyncLoad Id.
335    */
336   struct AsyncLoadingInfo
337   {
338     AsyncLoadingInfo( TextureId textureId )
339     : textureId( textureId ),
340       loadId( 0 )
341     {
342     }
343
344     TextureId           textureId;   ///< The external Texture Id assigned to this load
345     unsigned short      loadId;      ///< The load Id used by the async loader to reference this load
346   };
347
348   /**
349    * @brief This struct is used within a container to manage atlas creation and destruction.
350    */
351   struct AtlasInfo
352   {
353     AtlasInfo( Toolkit::ImageAtlas atlas, TextureSet textureSet )
354     : atlas( atlas ),
355       textureSet( textureSet )
356     {
357     }
358
359     Toolkit::ImageAtlas                 atlas;                          ///< The ImageAtlas object
360     TextureSet                          textureSet;                     ///< The TextureSet is kept in the struct to allow fast lookup of TextureSet to Atlas
361   };
362
363   // Private typedefs:
364
365   typedef std::deque<AsyncLoadingInfo>  AsyncLoadingInfoContainerType;  ///< The container type used to manage Asynchronous loads in progress
366   typedef std::vector<AtlasInfo>        AtlasInfoContainerType;         ///< The container type used to manage Atlas creation and destruction
367   typedef std::vector<TextureInfo>      TextureInfoContainerType;       ///< The container type used to manage the life-cycle and caching of Textures
368
369   /**
370    * @brief Used internally to initiate a load.
371    * @param[in] textureInfo The TextureInfo struct associated with the Texture
372    * @return                True if the load was initiated
373    */
374   bool LoadTexture( TextureInfo& textureInfo );
375
376   /**
377    * Add the observer to the observer list
378    * @param[in] textureInfo The TextureInfo struct associated with the texture
379    * observer The observer wishing to observe the texture upload
380    */
381   void ObserveTexture( TextureInfo & textureInfo, TextureUploadObserver* observer );
382
383   /**
384    * @brief This signal handler is called when the async local loader finishes loading.
385    * @param[in] id        This is the async image loaders Id
386    * @param[in] pixelBuffer The loaded image data
387    */
388   void AsyncLocalLoadComplete( uint32_t id, Devel::PixelBuffer pixelBuffer );
389
390   /**
391    * @brief This signal handler is called when the async local loader finishes loading.
392    * @param[in] id        This is the async image loaders Id
393    * @param[in] pixelBuffer The loaded image data
394    */
395   void AsyncRemoteLoadComplete( uint32_t id, Devel::PixelBuffer pixelBuffer );
396
397   /**
398    * Common method to handle loading completion
399    * @param[in] container The Async loading container
400    * @param[in] id        This is the async image loaders Id
401    * @param[in] pixelBuffer The loaded image data
402    */
403   void AsyncLoadComplete( AsyncLoadingInfoContainerType& container, uint32_t id, Devel::PixelBuffer pixelBuffer );
404
405   /**
406    * @brief Performs Post-Load steps including atlasing.
407    * @param[in] textureInfo The struct associated with this Texture
408    * @param[in] pixelBuffer The image pixelBuffer
409    * @return    True if successful
410    */
411   void PostLoad( TextureManager::TextureInfo& textureInfo, Devel::PixelBuffer& pixelBuffer );
412
413   /**
414    * Check if there is a texture waiting to be masked. If there
415    * is then apply this mask and upload it.
416    * @param[in] maskTextureInfo The texture info of the mask that has just loaded.
417    */
418   void CheckForWaitingTexture( TextureInfo& maskTextureInfo );
419
420   /**
421    * Apply the mask to the pixelBuffer.
422    * @param[in] pixelBuffer The pixelBuffer to apply the mask to
423    * @param[in] maskTextureId The texture id of the mask.
424    * @param[in] contentScale The factor to scale the content
425    * @param[in] cropToMask Whether to crop the content to the mask size
426    */
427   void ApplyMask( Devel::PixelBuffer& pixelBuffer, TextureId maskTextureId,
428                   float contentScale, bool cropToMask );
429
430   /**
431    * Upload the texture specified in pixelBuffer to the appropriate location
432    * @param[in] pixelBuffer The image data to upload
433    * @param[in] textureInfo The texture info containing the location to
434    * store the data to.
435    */
436   void UploadTexture( Devel::PixelBuffer& pixelBuffer, TextureInfo& textureInfo );
437
438   /**
439    * Mark the texture as complete, and inform observers
440    * @param[in] textureInfo The struct associated with this Texture
441    */
442   void UploadComplete( TextureInfo& textureInfo );
443
444   /**
445    * Notify the current observers that the texture upload is complete,
446    * then remove the observers from the list.
447    * @param[in] textureInfo The struct associated with this Texture
448    * @param[in] success If the pixel data was retrieved successfully and uploaded to GPU
449    */
450   void NotifyObservers( TextureInfo& textureInfo, bool success );
451
452   /**
453    * @brief Generates a new, unique TextureId
454    * @return A unique TextureId
455    */
456   TextureManager::TextureId GenerateUniqueTextureId();
457
458   /**
459    * @brief Used to lookup an index into the TextureInfoContainer from a TextureId
460    * @param[in] textureId The TextureId to look up
461    * @return              The cache index
462    */
463   int GetCacheIndexFromId( TextureId textureId );
464
465
466   /**
467    * @brief Generates a hash for caching based on the input parameters.
468    * Only applies size, fitting mode andsampling mode if the size is specified.
469    * Only applies maskTextureId if it isn't INVALID_TEXTURE_ID
470    * Always applies useAtlas.
471    * @param[in] url          The URL of the image to load
472    * @param[in] size         The image size
473    * @param[in] fittingMode  The FittingMode to use
474    * @param[in] samplingMode The SamplingMode to use
475    * @param[in] useAtlas     True if atlased
476    * @param[in] maskTextureId The masking texture id (or INVALID_TEXTURE_ID)
477    * @return                 A hash of the provided data for caching.
478    */
479   TextureHash GenerateHash( const std::string& url, const ImageDimensions size,
480                             const FittingMode::Type fittingMode,
481                             const Dali::SamplingMode::Type samplingMode, const UseAtlas useAtlas,
482                             TextureId maskTextureId );
483   /**
484    * @brief Looks up a cached texture by its hash.
485    * If found, the given parameters are used to check there is no hash-collision.
486    * @param[in] hash          The hash to look up
487    * @param[in] url           The URL of the image to load
488    * @param[in] size          The image size
489    * @param[in] fittingMode   The FittingMode to use
490    * @param[in] samplingMode  The SamplingMode to use
491    * @param[in] useAtlas      True if atlased
492    * @param[in] maskTextureId Optional texture ID to use to mask this image
493    * @return A TextureId of a cached Texture if found. Or INVALID_TEXTURE_ID if not found.
494    */
495   TextureManager::TextureId FindCachedTexture(
496     const TextureManager::TextureHash hash,
497     const std::string& url,
498     const ImageDimensions size,
499     const FittingMode::Type fittingMode,
500     const Dali::SamplingMode::Type samplingMode,
501     const bool useAtlas,
502     TextureId maskTextureId );
503
504 private:
505
506   /**
507    * @brief Helper class to keep the relation between AsyncImageLoader and corresponding LoadingInfo container
508    */
509   class AsyncLoadingHelper : public ConnectionTracker
510   {
511   public:
512     /**
513      * @brief Create an AsyncLoadingHelper.
514      * @param[in] textureManager Reference to the texture manager
515      */
516     AsyncLoadingHelper(TextureManager& textureManager);
517
518     /**
519      * @brief Load a new texture.
520      * @param[in] textureId             TextureId to reference the texture that will be loaded
521      * @param[in] url                   The URL of the image to load
522      * @param[in] desiredSize           The size the image is likely to appear at. This can be set to 0,0 for automatic
523      * @param[in] fittingMode           The FittingMode to use
524      * @param[in] samplingMode          The SamplingMode to use
525      * @param[in] orientationCorrection Whether to use image metadata to rotate or flip the image, e.g., from portrait to landscape
526      */
527     void Load(TextureId textureId,
528               const VisualUrl& url,
529               ImageDimensions desiredSize,
530               FittingMode::Type fittingMode,
531               SamplingMode::Type samplingMode,
532               bool orientationCorrection);
533
534   public:
535     AsyncLoadingHelper(const AsyncLoadingHelper&) = delete;
536     AsyncLoadingHelper& operator=(const AsyncLoadingHelper&) = delete;
537
538     AsyncLoadingHelper(AsyncLoadingHelper&& rhs);
539     AsyncLoadingHelper& operator=(AsyncLoadingHelper&&rhs) = delete;
540
541   private:
542     /**
543      * @brief Main constructor that used by all other constructors
544      */
545     AsyncLoadingHelper(Toolkit::AsyncImageLoader loader,
546                        TextureManager& textureManager,
547                        AsyncLoadingInfoContainerType&& loadingInfoContainer);
548
549     /**
550      * @brief Callback to be called when texture loading is complete, it passes the pixel buffer on to texture manager.
551      * @param[in] id          Loader id
552      * @param[in] pixelBuffer Image data
553      */
554     void AsyncLoadComplete(uint32_t id, Devel::PixelBuffer pixelBuffer);
555
556   private:
557     Toolkit::AsyncImageLoader     mLoader;
558     TextureManager&               mTextureManager;
559     AsyncLoadingInfoContainerType mLoadingInfoContainer;
560   };
561
562   struct ExternalTextureInfo
563   {
564     TextureId textureId;
565     TextureSet textureSet;
566   };
567
568 private:
569
570   /**
571    * Deleted copy constructor.
572    */
573   TextureManager( const TextureManager& ) = delete;
574
575   /**
576    * Deleted assignment operator.
577    */
578   TextureManager& operator=( const TextureManager& rhs ) = delete;
579
580   /**
581    * This is called by the TextureManagerUploadObserver when an observer is destroyed.
582    * We use the callback to know when to remove an observer from our notify list.
583    * @param[in] observer The observer that generated the callback
584    */
585   void ObserverDestroyed( TextureUploadObserver* observer );
586
587 private:  // Member Variables:
588
589   AtlasInfoContainerType                        mAtlasContainer;       ///< Used to manage Atlas creation and destruction
590   TextureInfoContainerType                      mTextureInfoContainer; ///< Used to manage the life-cycle and caching of Textures
591   RoundRobinContainerView< AsyncLoadingHelper > mAsyncLocalLoaders;    ///< The Asynchronous image loaders used to provide all local async loads
592   RoundRobinContainerView< AsyncLoadingHelper > mAsyncRemoteLoaders;   ///< The Asynchronous image loaders used to provide all remote async loads
593   std::vector< ExternalTextureInfo >            mExternalTextures;     ///< Externally provided textures
594   TextureId                                     mCurrentTextureId;     ///< The current value used for the unique Texture Id generation
595
596 };
597
598
599 } // name Internal
600
601 } // namespace Toolkit
602
603 } // namespace Dali
604
605 #endif // DALI_TOOLKIT_TEXTURE_MANAGER_IMPL_H