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