Fix feedback style error message.
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / texture-manager.h
1 #ifndef DALI_TOOLKIT_TEXTURE_MANAGER_H
2 #define DALI_TOOLKIT_TEXTURE_MANAGER_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 <string>
22 #include <dali/public-api/common/dali-vector.h>
23 #include <dali/public-api/object/ref-object.h>
24 #include <dali/public-api/rendering/texture-set.h>
25 #include <dali/devel-api/common/owner-container.h>
26 #include <deque>
27
28 // INTERNAL INCLUDES
29 #include <dali-toolkit/devel-api/image-loader/image-atlas.h>
30 #include <dali-toolkit/public-api/image-loader/async-image-loader.h>
31 #include <dali-toolkit/internal/visuals/texture-upload-observer.h>
32 #include <dali-toolkit/internal/visuals/visual-url.h>
33
34
35 namespace Dali
36 {
37
38 namespace Toolkit
39 {
40
41 namespace Internal
42 {
43
44 /**
45  * The TextureManager provides a common Image loading API for Visuals.
46  *
47  * The TextureManager is responsible for providing sync, async, atlased and non-atlased loads.
48  * Texture caching is provided and performed when possible.
49  * Broken Images are automatically provided on load failure.
50  */
51 class TextureManager : public ConnectionTracker
52 {
53 public:
54
55   typedef int32_t TextureId;       ///< The TextureId type. This is used as a handle to refer to a particular Texture.
56   static const int INVALID_TEXTURE_ID = -1; ///< Used to represent a null TextureId or error
57
58   enum UseAtlas
59   {
60     NO_ATLAS,
61     USE_ATLAS
62   };
63
64   enum LoadType
65   {
66     LOAD_ASYNCHRONOUSLY,
67     LOAD_SYNCHRONOUSLY
68   };
69
70   /**
71    * @brief The LoadState Enumeration represents the current state of a particular Textures life-cycle.
72    */
73   enum LoadState
74   {
75     NOT_STARTED,     ///< Default
76     LOADING,         ///< Loading has been started, but not finished.
77     UPLOADED,        ///< Loaded (and ready).
78     CANCELLED,       ///< Removed before loading completed
79   };
80
81 public:
82
83   /**
84    * Constructor.
85    */
86   TextureManager();
87
88   /**
89    * Destructor.
90    */
91   ~TextureManager();
92
93
94 // TextureManager Main API:
95
96   /**
97    * @brief Requests an image load of the given URL.
98    *
99    * The parameters are used to specify how the image is loaded.
100    * The observer has the UploadComplete method called when the load is ready.
101    *
102    * When the client has finished with the Texture, Remove() should be called.
103    *
104    * @param[in] url               The URL of the image to load
105    * @param[in] desiredSize       The size the image is likely to appear at. This can be set to 0,0 for automatic
106    * @param[in] fittingMode       The FittingMode to use
107    * @param[in] samplingMode      The SamplingMode to use
108    * @param[in] useAtlasing       Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be loaded, and marked successful,
109    *                              but "useAtlasing" will be set to false in the "UploadCompleted" callback from the TextureManagerUploadObserver.
110    * @param[in] observer          The client object should inherit from this and provide the "UploadCompleted" virtual.
111    *                              This is called when an image load completes (or fails).
112    * @return                      A TextureId to use as a handle to reference this Texture
113    */
114   TextureId RequestLoad( const VisualUrl&         url,
115                          const ImageDimensions    desiredSize,
116                          FittingMode::Type        fittingMode,
117                          Dali::SamplingMode::Type samplingMode,
118                          const UseAtlas           useAtlasing,
119                          TextureUploadObserver*   observer );
120
121   /**
122    * @brief Remove a Texture from the TextureManager.
123    *
124    * Textures are cached and therefore only the removal of the last
125    * occurrence of a Texture will cause its removal internally.
126    *
127    * @param[in] textureId The ID of the Texture to remove.
128    */
129   void Remove( const TextureManager::TextureId textureId );
130
131   /**
132    * @brief Get the current state of a texture
133    * @param[in] textureId The texture id to query
134    * @return The loading state if the texture is valid, or NOT_STARTED if the textureId
135    * is not valid.
136    */
137   LoadState GetTextureState( TextureId textureId );
138
139   /**
140    * @brief Get the associated texture set if the texture id is valid
141    * @param[in] textureId The texture Id to look up
142    * @return the associated texture set, or an empty handle if textureId is not valid
143    */
144   TextureSet GetTextureSet( TextureId textureId );
145
146 private:
147
148
149   typedef size_t TextureHash; ///< The type used to store the hash used for Texture caching.
150
151   /**
152    * @brief This struct is used to manage the life-cycle of Texture loading and caching.
153    * TODO-TX: pimpl this
154    */
155   struct TextureInfo
156   {
157     TextureInfo( TextureId textureId,
158                  const VisualUrl& url,
159                  ImageDimensions desiredSize,
160                  FittingMode::Type fittingMode,
161                  Dali::SamplingMode::Type samplingMode,
162                  bool loadSynchronously,
163                  UseAtlas useAtlas,
164                  TextureManager::TextureHash hash )
165     : url( url ),
166       desiredSize( desiredSize ),
167       useSize( desiredSize ),
168       atlasRect( 0.0f, 0.0f, 1.0f, 1.0f ), // Full atlas rectangle
169       textureId( textureId ),
170       hash( hash ),
171       referenceCount( 1u ),
172       loadState( NOT_STARTED ),
173       fittingMode( fittingMode ),
174       samplingMode( samplingMode ),
175       loadSynchronously( loadSynchronously ),
176       useAtlas( useAtlas ),
177       loadingSucceeded( false )
178     {
179     }
180
181     /**
182      * Container type used to store all observer clients of this Texture
183      */
184     typedef Dali::Vector< TextureUploadObserver* > ObserverListType;
185
186     ObserverListType observerList; ///< Container used to store all observer clients of this Texture
187     Toolkit::ImageAtlas atlas;     ///< The atlas this Texture lays within (if any)
188     PixelData pixelData;           ///< The PixelData holding the image data (this is used if atlasing is deferred)
189     TextureSet textureSet;         ///< The TextureSet holding the Texture
190     VisualUrl url;                 ///< The URL of the image
191     ImageDimensions desiredSize;   ///< The size requested
192     ImageDimensions useSize;       ///< The size used
193     Vector4 atlasRect;             ///< The atlas rect used if atlased
194     TextureId textureId;           ///< The TextureId associated with this Texture
195     TextureManager::TextureHash hash; ///< The hash used to cache this Texture
196     int16_t referenceCount;        ///< The reference count of clients using this Texture
197     LoadState loadState:3;         ///< The load state showing the load progress of the Texture
198     FittingMode::Type fittingMode:2; ///< The requested FittingMode
199     Dali::SamplingMode::Type samplingMode:3; ///< The requested SamplingMode
200     bool loadSynchronously;        ///< True if synchronous loading was requested
201     UseAtlas useAtlas; ///< USE_ATLAS if an atlas was requested. This is updated to false if atlas is not used
202     bool loadingSucceeded;         ///< True if the image was loaded successfully
203   };
204
205   // Structs:
206
207   /**
208    * Struct to hold information about a requested Async load.
209    * This is used to look up a TextureManager::TextureId from the returned AsyncLoad Id.
210    */
211   struct AsyncLoadingInfo
212   {
213     AsyncLoadingInfo( TextureId textureId )
214     : textureId( textureId ),
215       loadId( 0 )
216     {
217     }
218
219     TextureId           textureId;   ///< The external Texture Id assigned to this load
220     unsigned short      loadId;      ///< The load Id used by the async loader to reference this load
221   };
222
223   /**
224    * @brief This struct is used within a container to manage atlas creation and destruction.
225    */
226   struct AtlasInfo
227   {
228     AtlasInfo( Toolkit::ImageAtlas atlas, TextureSet textureSet )
229     : atlas( atlas ),
230       textureSet( textureSet )
231     {
232     }
233
234     Toolkit::ImageAtlas                 atlas;                          ///< The ImageAtlas object
235     TextureSet                          textureSet;                     ///< The TextureSet is kept in the struct to allow fast lookup of TextureSet to Atlas
236   };
237
238   // Private typedefs:
239
240   typedef std::deque<AsyncLoadingInfo>  AsyncLoadingInfoContainerType;  ///< The container type used to manage Asynchronous loads in progress
241   typedef std::vector<AtlasInfo>        AtlasInfoContainerType;         ///< The container type used to manage Atlas creation and destruction
242   typedef std::vector<TextureInfo>      TextureInfoContainerType;       ///< The container type used to manage the life-cycle and caching of Textures
243
244   /**
245    * @brief Used internally to initiate a load.
246    * @param[in] textureInfo The TextureInfo struct associated with the Texture
247    * @return                True if the load was initiated
248    */
249   bool LoadTexture( TextureInfo& textureInfo );
250
251   /**
252    * Add the observer to the observer list
253    * @param[in] textureInfo The TextureInfo struct associated with the texture
254    * observer The observer wishing to observe the texture upload
255    */
256   void ObserveTexture( TextureInfo & textureInfo, TextureUploadObserver* observer );
257
258   /**
259    * @brief This signal handler is called when the async local loader finishes loading.
260    * @param[in] id        This is the async image loaders Id
261    * @param[in] pixelData The loaded image data
262    */
263   void AsyncLocalLoadComplete( uint32_t id, PixelData pixelData );
264
265   /**
266    * @brief This signal handler is called when the async local loader finishes loading.
267    * @param[in] id        This is the async image loaders Id
268    * @param[in] pixelData The loaded image data
269    */
270   void AsyncRemoteLoadComplete( uint32_t id, PixelData pixelData );
271
272   /**
273    * Common method to handle loading completion
274    * @param[in] container The Async loading container
275    * @param[in] id        This is the async image loaders Id
276    * @param[in] pixelData The loaded image data
277    */
278   void AsyncLoadComplete( AsyncLoadingInfoContainerType& container, uint32_t id, PixelData pixelData );
279
280   /**
281    * @brief Performs Post-Load steps including atlasing.
282    * @param[in]           textureInfo The struct associated with this Texture
283    * @param[in]           pixelData   The image pixelData
284    * @return                          True if successful
285    */
286   bool PostLoad( TextureManager::TextureInfo& textureInfo, PixelData pixelData );
287
288   /**
289    * @brief Generates a new, unique TextureId
290    * @return A unique TextureId
291    */
292   TextureManager::TextureId GenerateUniqueTextureId();
293
294   /**
295    * @brief Used to lookup an index into the TextureInfoContainer from a TextureId
296    * @param[in] textureId The TextureId to look up
297    * @return              The cache index
298    */
299   int GetCacheIndexFromId( TextureId textureId );
300
301
302   /**
303    * @brief Generates a hash for caching based on the input parameters.
304    * @param[in] url          The URL of the image to load
305    * @param[in] size         The image size
306    * @param[in] fittingMode  The FittingMode to use
307    * @param[in] samplingMode The SamplingMode to use
308    * @param[in] useAtlas     True if atlased
309    * @return                 A hash of the provided data for caching.
310    */
311   TextureHash GenerateHash( const std::string& url, const ImageDimensions size,
312                             const FittingMode::Type fittingMode,
313                             const Dali::SamplingMode::Type samplingMode, const UseAtlas useAtlas );
314
315   /**
316    * @brief Looks up a cached texture by its hash.
317    * If found, the given parameters are used to check there is no hash-collision.
318    * @param[in] hash The hash to look up
319    * @param[in] url          The URL of the image to load
320    * @param[in] size         The image size
321    * @param[in] fittingMode  The FittingMode to use
322    * @param[in] samplingMode The SamplingMode to use
323    * @param[in] useAtlas     True if atlased
324    * @return                 A TextureId of a cached Texture if found. Or INVALID_TEXTURE_ID if not found.
325    */
326   TextureManager::TextureId FindCachedTexture( const TextureManager::TextureHash hash, const std::string& url, const ImageDimensions size,
327       const FittingMode::Type fittingMode, const Dali::SamplingMode::Type samplingMode, const bool useAtlas );
328
329
330 private:
331
332   /**
333    * Undefined copy constructor.
334    */
335   TextureManager( const TextureManager& );
336
337   /**
338    * Undefined assignment operator.
339    */
340   TextureManager& operator=( const TextureManager& rhs );
341
342   /**
343    * This is called by the TextureManagerUploadObserver when an observer is destroyed.
344    * We use the callback to know when to remove an observer from our notify list.
345    * @param[in] observer The observer that generated the callback
346    */
347   void ObserverDestroyed( TextureUploadObserver* observer );
348
349 private:  // Member Variables:
350
351   AsyncLoadingInfoContainerType         mAsyncLocalLoadingInfoContainer;     ///< Used to manage Asynchronous loads in progress
352   AsyncLoadingInfoContainerType         mAsyncRemoteLoadingInfoContainer;     ///< Used to manage Asynchronous loads in progress
353   AtlasInfoContainerType                mAtlasContainer;                ///< Used to manage Atlas creation and destruction
354   TextureInfoContainerType              mTextureInfoContainer;          ///< Used to manage the life-cycle and caching of Textures
355   Toolkit::AsyncImageLoader             mAsyncLocalLoader;              ///< The Asynchronous image loader used to provide all local async loads
356   Toolkit::AsyncImageLoader             mAsyncRemoteLoader;             ///< The Asynchronous image loader used to provide all remote async loads
357   TextureId                             mCurrentTextureId;              ///< The current value used for the unique Texture Id generation
358
359 };
360
361
362 } // name Internal
363
364 } // namespace Toolkit
365
366 } // namespace Dali
367
368 #endif // DALI_TOOLKIT_TEXTURE_MANAGER_H