Fix DALI_DEBUG_RENDERING crash
[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 <memory>
25 #include <dali/public-api/common/dali-vector.h>
26 #include <dali/public-api/object/ref-object.h>
27 #include <dali/public-api/rendering/texture-set.h>
28 #include <dali/devel-api/common/owner-container.h>
29 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
30
31 // INTERNAL INCLUDES
32 #include <dali-toolkit/devel-api/image-loader/async-image-loader-devel.h>
33 #include <dali-toolkit/devel-api/image-loader/image-atlas.h>
34 #include <dali-toolkit/public-api/image-loader/async-image-loader.h>
35 #include <dali-toolkit/internal/visuals/texture-upload-observer.h>
36 #include <dali-toolkit/internal/visuals/visual-url.h>
37 #include <dali-toolkit/internal/helpers/round-robin-container-view.h>
38 #include <dali-toolkit/internal/image-loader/async-image-loader-impl.h>
39
40
41 namespace Dali
42 {
43
44 namespace Toolkit
45 {
46
47 namespace Internal
48 {
49 class ImageAtlasManager;
50 typedef IntrusivePtr<ImageAtlasManager> ImageAtlasManagerPtr;
51
52 /**
53  * The TextureManager provides a common Image loading API for Visuals.
54  *
55  * The TextureManager is responsible for providing sync, async, atlased and non-atlased loads.
56  * Texture caching is provided and performed when possible.
57  * Broken Images are automatically provided on load failure.
58  */
59 class TextureManager : public ConnectionTracker
60 {
61 public:
62
63   typedef int32_t TextureId;       ///< The TextureId type. This is used as a handle to refer to a particular Texture.
64   static const int INVALID_TEXTURE_ID = -1; ///< Used to represent a null TextureId or error
65
66   /**
67    * Whether the texture should be atlased or uploaded into it's own GPU texture
68    */
69   enum UseAtlas
70   {
71     NO_ATLAS,
72     USE_ATLAS
73   };
74
75   /**
76    * Whether the pixel data should be kept in TextureManager, or uploaded for rendering
77    */
78   enum StorageType
79   {
80     KEEP_PIXEL_BUFFER,
81     UPLOAD_TO_TEXTURE
82   };
83
84   /**
85    * Whether the texture should be loaded synchronously or asynchronously.
86    */
87   enum LoadType
88   {
89     LOAD_ASYNCHRONOUSLY,
90     LOAD_SYNCHRONOUSLY
91   };
92
93   /**
94    * @brief The LoadState Enumeration represents the current state of a particular Texture's life-cycle.
95    */
96   enum LoadState
97   {
98     NOT_STARTED,     ///< Default
99     LOADING,         ///< Loading has been started, but not finished.
100     LOAD_FINISHED,   ///< Loading has finished. (for CPU storage only)
101     WAITING_FOR_MASK,///< Loading has finished, but waiting for mask image
102     UPLOADED,        ///< Uploaded and ready. (For GPU upload only)
103     CANCELLED,       ///< Removed before loading completed
104     LOAD_FAILED      ///< Async loading failed, e.g. connection problem
105   };
106
107   /**
108    * @brief Types of reloading policies
109    */
110   enum class ReloadPolicy
111   {
112     CACHED = 0,             ///< Loads cached texture if it exists.
113     FORCED                  ///< Forces reloading of texture.
114   };
115
116   /**
117    * @brief Whether to multiply alpha into color channels on load
118    */
119   enum class MultiplyOnLoad
120   {
121     LOAD_WITHOUT_MULTIPLY = 0, ///< Don't modify the image
122     MULTIPLY_ON_LOAD           ///< Multiply alpha into color channels on load
123   };
124
125 public:
126
127   struct MaskingData
128   {
129     MaskingData();
130     ~MaskingData() = default;
131
132     VisualUrl mAlphaMaskUrl;
133     TextureManager::TextureId mAlphaMaskId;
134     float mContentScaleFactor;
135     bool mCropToMask;
136   };
137   using MaskingDataPointer = std::unique_ptr<MaskingData>;
138
139
140   /**
141    * Class to provide lifecycle event on destruction of texture manager.
142    */
143   struct LifecycleObserver
144   {
145     /**
146      * Called shortly before the texture manager is destroyed.
147      */
148     virtual void TextureManagerDestroyed() = 0;
149   };
150
151   /**
152    * Constructor.
153    */
154   TextureManager();
155
156   /**
157    * Destructor.
158    */
159   ~TextureManager();
160
161   // TextureManager Main API:
162
163   /**
164    * @brief Requests an image load of the given URL.
165    *
166    * The parameters are used to specify how the image is loaded.
167    * The observer has the UploadComplete method called when the load is ready.
168    *
169    * When the client has finished with the Texture, Remove() should be called.
170    *
171    * @param[in] url                   The URL of the image to load
172    * @param[in] desiredSize           The size the image is likely to appear at. This can be set to 0,0 for automatic
173    * @param[in] fittingMode           The FittingMode to use
174    * @param[in] samplingMode          The SamplingMode to use
175    * @param[in] maskInfo              Mask info structure
176    * @param[in] synchronousLoading    true if the URL should be loaded synchronously
177    * @param[out] textureId,           The textureId of the URL
178    * @param[out] textureRect          The rectangle within the texture atlas that this URL occupies
179    * @param[in,out] atlasingStatus    Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still
180    *                                  be loaded, and marked successful, but this will be set to false.
181    *                                  If atlasing succeeds, this will be set to true.
182    * @param[out] loadingStatus        The loading status of the texture
183    * @param[in] wrapModeU             Horizontal Wrap mode
184    * @param[in] wrapModeV             Vertical Wrap mode
185    * @param[in] textureObserver       The client object should inherit from this and provide the "UploadCompleted" virtual.
186    *                                  This is called when an image load completes (or fails).
187    * @param[in] atlasObserver         This is used if the texture is atlased, and will be called instead of
188    *                                  textureObserver.UploadCompleted
189    * @param[in] imageAtlasManager     The atlas manager to use for atlasing textures
190    * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data
191    * @param[in] reloadPolicy          Forces a reload of the texture even if already cached
192    * @param[in,out] preMultiplyOnLoad True if the image color should be multiplied by it's alpha. Set to false if the
193    *                                  image has no alpha channel
194    *
195    * @return                          The texture set containing the image, or empty if still loading.
196    */
197
198   TextureSet LoadTexture( const VisualUrl&             url,
199                           Dali::ImageDimensions        desiredSize,
200                           Dali::FittingMode::Type      fittingMode,
201                           Dali::SamplingMode::Type     samplingMode,
202                           const MaskingDataPointer&    maskInfo,
203                           bool                         synchronousLoading,
204                           TextureManager::TextureId&   textureId,
205                           Vector4&                     textureRect,
206                           bool&                        atlasingStatus,
207                           bool&                        loadingStatus,
208                           Dali::WrapMode::Type         wrapModeU,
209                           Dali::WrapMode::Type         wrapModeV,
210                           TextureUploadObserver*       textureObserver,
211                           AtlasUploadObserver*         atlasObserver,
212                           ImageAtlasManagerPtr         imageAtlasManager,
213                           bool                         orientationCorrection,
214                           TextureManager::ReloadPolicy reloadPolicy,
215                           MultiplyOnLoad&              preMultiplyOnLoad );
216
217   /**
218    * @brief Requests an image load of the given URL.
219    *
220    * The parameters are used to specify how the image is loaded.
221    * The observer has the UploadComplete method called when the load is ready.
222    *
223    * When the client has finished with the Texture, Remove() should be called.
224    *
225    * @param[in] url                   The URL of the image to load
226    * @param[in] desiredSize           The size the image is likely to appear at. This can be set to 0,0 for automatic
227    * @param[in] fittingMode           The FittingMode to use
228    * @param[in] samplingMode          The SamplingMode to use
229    * @param[in] useAtlasing           Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be loaded, and marked successful,
230    *                                  but "useAtlasing" will be set to false in the "UploadCompleted" callback from the TextureManagerUploadObserver.
231    * @param[in] observer              The client object should inherit from this and provide the "UploadCompleted" virtual.
232    *                                  This is called when an image load completes (or fails).
233    * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data
234    * @param[in] reloadPolicy          Forces a reload of the texture even if already cached
235    * @param[in,out] preMultiplyOnLoad     True if the image color should be multiplied by it's alpha. Set to false if the image has no alpha channel
236    * @return                          A TextureId to use as a handle to reference this Texture
237    */
238   TextureId RequestLoad( const VisualUrl&                   url,
239                          const ImageDimensions              desiredSize,
240                          FittingMode::Type                  fittingMode,
241                          Dali::SamplingMode::Type           samplingMode,
242                          const UseAtlas                     useAtlasing,
243                          TextureUploadObserver*             observer,
244                          bool                               orientationCorrection,
245                          TextureManager::ReloadPolicy       reloadPolicy,
246                          MultiplyOnLoad&                    preMultiplyOnLoad );
247
248   /**
249    * @brief Requests an image load of the given URL, when the texture has
250    * have loaded, it will perform a blend with the image mask, and upload
251    * the blended texture.
252    *
253    * The parameters are used to specify how the image is loaded.
254    * The observer has the UploadComplete method called when the load is ready.
255    *
256    * When the client has finished with the Texture, Remove() should be called.
257    *
258    * @param[in] url                   The URL of the image to load
259    * @param[in] maskTextureId         The texture id of an image to mask this with
260    *                                  (can be INVALID if no masking required)
261    * @param[in] contentScale          The scale factor to apply to the image before masking
262    * @param[in] desiredSize           The size the image is likely to appear at. This can be set to 0,0 for automatic
263    * @param[in] fittingMode           The FittingMode to use
264    * @param[in] samplingMode          The SamplingMode to use
265    * @param[in] useAtlasing           Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still
266    *                                  be loaded, and marked successful,
267    *                                  but "useAtlasing" will be set to false in the "UploadCompleted" callback from
268    *                                  the TextureManagerUploadObserver.
269    * @param[in] cropToMask            Only used with masking, this will crop the scaled image to the mask size.
270    *                                  If false, then the mask will be scaled to fit the image before being applied.
271    * @param[in] observer              The client object should inherit from this and provide the "UploadCompleted"
272    *                                  virtual.
273    *                                  This is called when an image load completes (or fails).
274    * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data
275    * @param[in] reloadPolicy          Forces a reload of the texture even if already cached
276    * @param[in] preMultiplyOnLoad     True if the image color should be multiplied by it's alpha. Set to false if the
277    *                                  image has no alpha channel
278    * @return                          A TextureId to use as a handle to reference this Texture
279    */
280   TextureId RequestLoad( const VisualUrl&                   url,
281                          TextureId                          maskTextureId,
282                          float                              contentScale,
283                          const ImageDimensions              desiredSize,
284                          FittingMode::Type                  fittingMode,
285                          Dali::SamplingMode::Type           samplingMode,
286                          const UseAtlas                     useAtlasing,
287                          bool                               cropToMask,
288                          TextureUploadObserver*             observer,
289                          bool                               orientationCorrection,
290                          TextureManager::ReloadPolicy       reloadPolicy,
291                          MultiplyOnLoad&                    preMultiplyOnLoad );
292
293   /**
294    * Requests a masking image to be loaded. This mask is not uploaded to GL,
295    * instead, it is stored in CPU memory, and can be used for CPU blending.
296    */
297   TextureId RequestMaskLoad( const VisualUrl& maskUrl );
298
299   /**
300    * @brief Remove a Texture from the TextureManager.
301    *
302    * Textures are cached and therefore only the removal of the last
303    * occurrence of a Texture will cause its removal internally.
304    *
305    * @param[in] textureId The ID of the Texture to remove.
306    */
307   void Remove( const TextureManager::TextureId textureId );
308
309   /**
310    * @brief Get the visualUrl associated with the texture id.
311    * @param[in] textureId The texture Id to get
312    * @return The visual Url associated with the texture id.
313    */
314   VisualUrl GetVisualUrl( TextureId textureId );
315
316   /**
317    * @brief Get the current state of a texture
318    * @param[in] textureId The texture id to query
319    * @return The loading state if the texture is valid, or NOT_STARTED if the textureId
320    * is not valid.
321    */
322   LoadState GetTextureState( TextureId textureId );
323
324   /**
325    * @brief Get the associated texture set if the texture id is valid
326    * @param[in] textureId The texture Id to look up
327    * @return the associated texture set, or an empty handle if textureId is not valid
328    */
329   TextureSet GetTextureSet( TextureId textureId );
330
331   /**
332    * Adds an external texture to the texture manager
333    * @param[in] texture The texture to add
334    * @return string containing the URL for the texture
335    */
336   std::string AddExternalTexture( TextureSet& texture );
337
338   /**
339    * Removes an external texture from texture manager
340    * @param[in] url The string containing the texture to remove
341    * @return handle to the texture
342    */
343   TextureSet RemoveExternalTexture( const std::string& url );
344
345   /**
346    * Add an observer to the object.
347    * @param[in] observer The observer to add.
348    */
349   void AddObserver( TextureManager::LifecycleObserver& observer );
350
351   /**
352    * Remove an observer from the object
353    * @pre The observer has already been added.
354    * @param[in] observer The observer to remove.
355    */
356   void RemoveObserver( TextureManager::LifecycleObserver& observer );
357
358   /**
359    * @brief Set an image to be used when a visual has failed to correctly render
360    * @param[in] brokenImageUrl The broken image url.
361    */
362   void SetBrokenImageUrl(const std::string& brokenImageUrl);
363
364 private:
365
366   /**
367    * @brief Requests an image load of the given URL, when the texture has
368    * have loaded, if there is a valid maskTextureId, it will perform a
369    * CPU blend with the mask, and upload the blend texture.
370    *
371    * The parameters are used to specify how the image is loaded.
372    * The observer has the UploadComplete method called when the load is ready.
373    *
374    * When the client has finished with the Texture, Remove() should be called.
375    *
376    * @param[in] url                   The URL of the image to load
377    * @param[in] maskTextureId         The texture id of an image to use as a mask. If no mask is required, then set
378    *                                  to INVALID_TEXTURE_ID
379    * @param[in] contentScale          The scaling factor to apply to the content when masking
380    * @param[in] desiredSize           The size the image is likely to appear at. This can be set to 0,0 for automatic
381    * @param[in] fittingMode           The FittingMode to use
382    * @param[in] samplingMode          The SamplingMode to use
383    * @param[in] useAtlasing           Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be
384    *                                  loaded, and marked successful, but "useAtlasing" will be set to false in the
385    *                                  "UploadCompleted" callback from the TextureManagerUploadObserver.
386    * @param[in] cropToMask            Whether to crop the target after masking, or scale the mask to the image before
387    *                                  masking.
388    * @param[in] storageType,          Whether the pixel data is stored in the cache or uploaded to the GPU
389    * @param[in] observer              The client object should inherit from this and provide the "UploadCompleted"
390    *                                  virtual.
391    *                                  This is called when an image load completes (or fails).
392    * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data
393    * @param[in] reloadPolicy          Forces a reload of the texture even if already cached
394    * @param[in] preMultiplyOnLoad     True if the image color should be multiplied by it's alpha. Set to false if
395    *                                  there is no alpha
396    * @return                          A TextureId to use as a handle to reference this Texture
397    */
398   TextureId RequestLoadInternal(
399     const VisualUrl&                    url,
400     TextureId                           maskTextureId,
401     float                               contentScale,
402     const ImageDimensions               desiredSize,
403     FittingMode::Type                   fittingMode,
404     Dali::SamplingMode::Type            samplingMode,
405     UseAtlas                            useAtlas,
406     bool                                cropToMask,
407     StorageType                         storageType,
408     TextureUploadObserver*              observer,
409     bool                                orientationCorrection,
410     TextureManager::ReloadPolicy        reloadPolicy,
411     MultiplyOnLoad&                     preMultiplyOnLoad );
412
413   /**
414    * @brief Get the current state of a texture
415    * @param[in] textureId The texture id to query
416    * @return The loading state if the texture is valid, or NOT_STARTED if the textureId
417    * is not valid.
418    */
419   LoadState GetTextureStateInternal( TextureId textureId );
420
421   typedef size_t TextureHash; ///< The type used to store the hash used for Texture caching.
422
423   /**
424    * @brief This struct is used to manage the life-cycle of Texture loading and caching.
425    */
426   struct TextureInfo
427   {
428     TextureInfo( TextureId textureId,
429                  TextureId maskTextureId,
430                  const VisualUrl& url,
431                  ImageDimensions desiredSize,
432                  float scaleFactor,
433                  FittingMode::Type fittingMode,
434                  Dali::SamplingMode::Type samplingMode,
435                  bool loadSynchronously,
436                  bool cropToMask,
437                  UseAtlas useAtlas,
438                  TextureManager::TextureHash hash,
439                  bool orientationCorrection,
440                  bool preMultiplyOnLoad )
441     : url( url ),
442       desiredSize( desiredSize ),
443       useSize( desiredSize ),
444       atlasRect( 0.0f, 0.0f, 1.0f, 1.0f ), // Full atlas rectangle
445       textureId( textureId ),
446       maskTextureId( maskTextureId ),
447       hash( hash ),
448       scaleFactor( scaleFactor ),
449       referenceCount( 1u ),
450       loadState( NOT_STARTED ),
451       fittingMode( fittingMode ),
452       samplingMode( samplingMode ),
453       storageType( UPLOAD_TO_TEXTURE ),
454       loadSynchronously( loadSynchronously ),
455       useAtlas( useAtlas ),
456       cropToMask( cropToMask ),
457       orientationCorrection( true ),
458       preMultiplyOnLoad( preMultiplyOnLoad ),
459       preMultiplied( false )
460     {
461     }
462
463     /**
464      * Container type used to store all observer clients of this Texture
465      */
466     typedef Dali::Vector< TextureUploadObserver* > ObserverListType;
467
468     ObserverListType observerList; ///< Container used to store all observer clients of this Texture
469     Toolkit::ImageAtlas atlas;     ///< The atlas this Texture lays within (if any)
470     Devel::PixelBuffer pixelBuffer;///< The PixelBuffer holding the image data (May be empty after upload)
471     TextureSet textureSet;         ///< The TextureSet holding the Texture
472     VisualUrl url;                 ///< The URL of the image
473     ImageDimensions desiredSize;   ///< The size requested
474     ImageDimensions useSize;       ///< The size used
475     Vector4 atlasRect;             ///< The atlas rect used if atlased
476     TextureId textureId;           ///< The TextureId associated with this Texture
477     TextureId maskTextureId;       ///< The mask TextureId to be applied on load
478     TextureManager::TextureHash hash; ///< The hash used to cache this Texture
479     float scaleFactor;             ///< The scale factor to apply to the Texture when masking
480     int16_t referenceCount;        ///< The reference count of clients using this Texture
481     LoadState loadState:3;         ///< The load state showing the load progress of the Texture
482     FittingMode::Type fittingMode:2; ///< The requested FittingMode
483     Dali::SamplingMode::Type samplingMode:3; ///< The requested SamplingMode
484     StorageType storageType:1;     ///< CPU storage / GPU upload;
485     bool loadSynchronously:1;      ///< True if synchronous loading was requested
486     UseAtlas useAtlas:1;           ///< USE_ATLAS if an atlas was requested.
487                                    ///< This is updated to false if atlas is not used
488     bool cropToMask:1;             ///< true if the image should be cropped to the mask size.
489     bool orientationCorrection:1;  ///< true if the image should be rotated to match exif orientation data
490     bool preMultiplyOnLoad:1;      ///< true if the image's color should be multiplied by it's alpha
491     bool preMultiplied:1;          ///< true if the image's color was multiplied by it's alpha
492   };
493
494   // Structs:
495
496   /**
497    * Struct to hold information about a requested Async load.
498    * This is used to look up a TextureManager::TextureId from the returned AsyncLoad Id.
499    */
500   struct AsyncLoadingInfo
501   {
502     AsyncLoadingInfo( TextureId textureId )
503     : textureId( textureId ),
504       loadId( 0 )
505     {
506     }
507
508     TextureId           textureId;   ///< The external Texture Id assigned to this load
509     uint32_t            loadId;      ///< The load Id used by the async loader to reference this load
510   };
511
512   // Private typedefs:
513
514   typedef std::deque<AsyncLoadingInfo>  AsyncLoadingInfoContainerType;  ///< The container type used to manage Asynchronous loads in progress
515   typedef std::vector<TextureInfo>      TextureInfoContainerType;       ///< The container type used to manage the life-cycle and caching of Textures
516
517   /**
518    * @brief Used internally to initiate a load.
519    * @param[in] textureInfo The TextureInfo struct associated with the Texture
520    * @return                True if the load was initiated
521    */
522   bool LoadTexture( TextureInfo& textureInfo );
523
524   /**
525    * Add the observer to the observer list
526    * @param[in] textureInfo The TextureInfo struct associated with the texture
527    * observer The observer wishing to observe the texture upload
528    */
529   void ObserveTexture( TextureInfo & textureInfo, TextureUploadObserver* observer );
530
531   /**
532    * @brief This signal handler is called when the async local loader finishes loading.
533    * @param[in] id        This is the async image loaders Id
534    * @param[in] pixelBuffer The loaded image data
535    */
536   void AsyncLocalLoadComplete( uint32_t id, Devel::PixelBuffer pixelBuffer );
537
538   /**
539    * @brief This signal handler is called when the async local loader finishes loading.
540    * @param[in] id        This is the async image loaders Id
541    * @param[in] pixelBuffer The loaded image data
542    */
543   void AsyncRemoteLoadComplete( uint32_t id, Devel::PixelBuffer pixelBuffer );
544
545   /**
546    * Common method to handle loading completion
547    * @param[in] container The Async loading container
548    * @param[in] id        This is the async image loaders Id
549    * @param[in] pixelBuffer The loaded image data
550    */
551   void AsyncLoadComplete( AsyncLoadingInfoContainerType& container, uint32_t id, Devel::PixelBuffer pixelBuffer );
552
553   /**
554    * @brief Performs Post-Load steps including atlasing.
555    * @param[in] textureInfo The struct associated with this Texture
556    * @param[in] pixelBuffer The image pixelBuffer
557    * @return    True if successful
558    */
559   void PostLoad( TextureManager::TextureInfo& textureInfo, Devel::PixelBuffer& pixelBuffer );
560
561   /**
562    * Check if there is a texture waiting to be masked. If there
563    * is then apply this mask and upload it.
564    * @param[in] maskTextureInfo The texture info of the mask that has just loaded.
565    */
566   void CheckForWaitingTexture( TextureInfo& maskTextureInfo );
567
568   /**
569    * Apply the mask to the pixelBuffer.
570    * @param[in] pixelBuffer The pixelBuffer to apply the mask to
571    * @param[in] maskTextureId The texture id of the mask.
572    * @param[in] contentScale The factor to scale the content
573    * @param[in] cropToMask Whether to crop the content to the mask size
574    */
575   void ApplyMask( Devel::PixelBuffer& pixelBuffer, TextureId maskTextureId,
576                   float contentScale, bool cropToMask );
577
578   /**
579    * Upload the texture specified in pixelBuffer to the appropriate location
580    * @param[in] pixelBuffer The image data to upload
581    * @param[in] textureInfo The texture info containing the location to
582    * store the data to.
583    */
584   void UploadTexture( Devel::PixelBuffer& pixelBuffer, TextureInfo& textureInfo );
585
586   /**
587    * Mark the texture as complete, and inform observers
588    * @param[in] textureInfo The struct associated with this Texture
589    */
590   void UploadComplete( TextureInfo& textureInfo );
591
592   /**
593    * Notify the current observers that the texture upload is complete,
594    * then remove the observers from the list.
595    * @param[in] textureInfo The struct associated with this Texture
596    * @param[in] success If the pixel data was retrieved successfully and uploaded to GPU
597    */
598   void NotifyObservers( TextureInfo& textureInfo, bool success );
599
600   /**
601    * @brief Generates a new, unique TextureId
602    * @return A unique TextureId
603    */
604   TextureManager::TextureId GenerateUniqueTextureId();
605
606   /**
607    * @brief Used to lookup an index into the TextureInfoContainer from a TextureId
608    * @param[in] textureId The TextureId to look up
609    * @return              The cache index
610    */
611   int GetCacheIndexFromId( TextureId textureId );
612
613
614   /**
615    * @brief Generates a hash for caching based on the input parameters.
616    * Only applies size, fitting mode andsampling mode if the size is specified.
617    * Only applies maskTextureId if it isn't INVALID_TEXTURE_ID
618    * Always applies useAtlas.
619    * @param[in] url          The URL of the image to load
620    * @param[in] size         The image size
621    * @param[in] fittingMode  The FittingMode to use
622    * @param[in] samplingMode The SamplingMode to use
623    * @param[in] useAtlas     True if atlased
624    * @param[in] maskTextureId The masking texture id (or INVALID_TEXTURE_ID)
625    * @return                 A hash of the provided data for caching.
626    */
627   TextureHash GenerateHash( const std::string& url, const ImageDimensions size,
628                             const FittingMode::Type fittingMode,
629                             const Dali::SamplingMode::Type samplingMode, const UseAtlas useAtlas,
630                             TextureId maskTextureId,
631                             MultiplyOnLoad preMultiplyOnLoad);
632   /**
633    * @brief Looks up a cached texture by its hash.
634    * If found, the given parameters are used to check there is no hash-collision.
635    * @param[in] hash          The hash to look up
636    * @param[in] url           The URL of the image to load
637    * @param[in] size          The image size
638    * @param[in] fittingMode   The FittingMode to use
639    * @param[in] samplingMode  The SamplingMode to use
640    * @param[in] useAtlas      True if atlased
641    * @param[in] maskTextureId Optional texture ID to use to mask this image
642    * @return A TextureId of a cached Texture if found. Or INVALID_TEXTURE_ID if not found.
643    */
644   TextureManager::TextureId FindCachedTexture(
645     const TextureManager::TextureHash hash,
646     const std::string& url,
647     const ImageDimensions size,
648     const FittingMode::Type fittingMode,
649     const Dali::SamplingMode::Type samplingMode,
650     const bool useAtlas,
651     TextureId maskTextureId,
652     MultiplyOnLoad preMultiplyOnLoad);
653
654 private:
655
656   /**
657    * @brief Helper class to keep the relation between AsyncImageLoader and corresponding LoadingInfo container
658    */
659   class AsyncLoadingHelper : public ConnectionTracker
660   {
661   public:
662     /**
663      * @brief Create an AsyncLoadingHelper.
664      * @param[in] textureManager Reference to the texture manager
665      */
666     AsyncLoadingHelper(TextureManager& textureManager);
667
668     /**
669      * @brief Load a new texture.
670      * @param[in] textureId             TextureId to reference the texture that will be loaded
671      * @param[in] url                   The URL of the image to load
672      * @param[in] desiredSize           The size the image is likely to appear at.
673      *                                  This can be set to 0,0 for automatic
674      * @param[in] fittingMode           The FittingMode to use
675      * @param[in] samplingMode          The SamplingMode to use
676      * @param[in] orientationCorrection Whether to use image metadata to rotate or flip the image,
677      *                                  e.g., from portrait to landscape
678      */
679     void Load(TextureId textureId,
680               const VisualUrl& url,
681               ImageDimensions desiredSize,
682               FittingMode::Type fittingMode,
683               SamplingMode::Type samplingMode,
684               bool orientationCorrection);
685
686   public:
687     AsyncLoadingHelper(const AsyncLoadingHelper&) = delete;
688     AsyncLoadingHelper& operator=(const AsyncLoadingHelper&) = delete;
689
690     AsyncLoadingHelper(AsyncLoadingHelper&& rhs);
691     AsyncLoadingHelper& operator=(AsyncLoadingHelper&&rhs) = delete;
692
693   private:
694     /**
695      * @brief Main constructor that used by all other constructors
696      */
697     AsyncLoadingHelper(Toolkit::AsyncImageLoader loader,
698                        TextureManager& textureManager,
699                        AsyncLoadingInfoContainerType&& loadingInfoContainer);
700
701     /**
702      * @brief Callback to be called when texture loading is complete, it passes the pixel buffer on to texture manager.
703      * @param[in] id          Loader id
704      * @param[in] pixelBuffer Image data
705      */
706     void AsyncLoadComplete(uint32_t id, Devel::PixelBuffer pixelBuffer);
707
708   private:
709     Toolkit::AsyncImageLoader     mLoader;
710     TextureManager&               mTextureManager;
711     AsyncLoadingInfoContainerType mLoadingInfoContainer;
712   };
713
714   struct ExternalTextureInfo
715   {
716     TextureId textureId;
717     TextureSet textureSet;
718   };
719
720 private:
721
722   /**
723    * Deleted copy constructor.
724    */
725   TextureManager( const TextureManager& ) = delete;
726
727   /**
728    * Deleted assignment operator.
729    */
730   TextureManager& operator=( const TextureManager& rhs ) = delete;
731
732   /**
733    * This is called by the TextureManagerUploadObserver when an observer is destroyed.
734    * We use the callback to know when to remove an observer from our notify list.
735    * @param[in] observer The observer that generated the callback
736    */
737   void ObserverDestroyed( TextureUploadObserver* observer );
738
739 private:  // Member Variables:
740
741   TextureInfoContainerType                      mTextureInfoContainer; ///< Used to manage the life-cycle and caching of Textures
742   RoundRobinContainerView< AsyncLoadingHelper > mAsyncLocalLoaders;    ///< The Asynchronous image loaders used to provide all local async loads
743   RoundRobinContainerView< AsyncLoadingHelper > mAsyncRemoteLoaders;   ///< The Asynchronous image loaders used to provide all remote async loads
744   std::vector< ExternalTextureInfo >            mExternalTextures;     ///< Externally provided textures
745   Dali::Vector<LifecycleObserver*>              mLifecycleObservers;   ///< Lifecycle observers of texture manager
746   std::string                                   mBrokenImageUrl;       ///< Broken image url
747   TextureId                                     mCurrentTextureId;     ///< The current value used for the unique Texture Id generation
748 };
749
750
751 } // name Internal
752
753 } // namespace Toolkit
754
755 } // namespace Dali
756
757 #endif // DALI_TOOLKIT_TEXTURE_MANAGER_IMPL_H