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