1 #ifndef DALI_TOOLKIT_TEXTURE_MANAGER_H
2 #define DALI_TOOLKIT_TEXTURE_MANAGER_H
5 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
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>
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>
45 * The TextureManager provides a common Image loading API for Visuals.
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.
51 class TextureManager : public ConnectionTracker
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
71 * @brief The LoadState Enumeration represents the current state of a particular Textures life-cycle.
75 NOT_STARTED, ///< Default
76 LOADING, ///< Loading has been started, but not finished.
77 UPLOADED, ///< Loaded (and ready).
78 CANCELLED, ///< Removed before loading completed
94 // TextureManager Main API:
97 * @brief Requests an image load of the given URL.
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.
102 * When the client has finished with the Texture, Remove() should be called.
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
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 );
122 * @brief Remove a Texture from the TextureManager.
124 * Textures are cached and therefore only the removal of the last
125 * occurrence of a Texture will cause its removal internally.
127 * @param[in] textureId The ID of the Texture to remove.
129 void Remove( const TextureManager::TextureId textureId );
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
137 LoadState GetTextureState( TextureId textureId );
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
144 TextureSet GetTextureSet( TextureId textureId );
149 typedef size_t TextureHash; ///< The type used to store the hash used for Texture caching.
152 * @brief This struct is used to manage the life-cycle of Texture loading and caching.
153 * TODO-TX: pimpl this
157 TextureInfo( TextureId textureId,
158 const VisualUrl& url,
159 ImageDimensions desiredSize,
160 FittingMode::Type fittingMode,
161 Dali::SamplingMode::Type samplingMode,
162 bool loadSynchronously,
164 TextureManager::TextureHash hash )
166 desiredSize( desiredSize ),
167 useSize( desiredSize ),
168 atlasRect( 0.0f, 0.0f, 1.0f, 1.0f ), // Full atlas rectangle
169 textureId( textureId ),
171 referenceCount( 1u ),
172 loadState( NOT_STARTED ),
173 fittingMode( fittingMode ),
174 samplingMode( samplingMode ),
175 loadSynchronously( loadSynchronously ),
176 useAtlas( useAtlas ),
177 loadingSucceeded( false )
182 * Container type used to store all observer clients of this Texture
184 typedef Dali::Vector< TextureUploadObserver* > ObserverListType;
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
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.
211 struct AsyncLoadingInfo
213 AsyncLoadingInfo( TextureId textureId )
214 : textureId( textureId ),
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
224 * @brief This struct is used within a container to manage atlas creation and destruction.
228 AtlasInfo( Toolkit::ImageAtlas atlas, TextureSet textureSet )
230 textureSet( textureSet )
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
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
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
249 bool LoadTexture( TextureInfo& textureInfo );
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
256 void ObserveTexture( TextureInfo & textureInfo, TextureUploadObserver* observer );
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
263 void AsyncLocalLoadComplete( uint32_t id, PixelData pixelData );
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
270 void AsyncRemoteLoadComplete( uint32_t id, PixelData pixelData );
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
278 void AsyncLoadComplete( AsyncLoadingInfoContainerType& container, uint32_t id, PixelData pixelData );
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
286 bool PostLoad( TextureManager::TextureInfo& textureInfo, PixelData pixelData );
289 * @brief Generates a new, unique TextureId
290 * @return A unique TextureId
292 TextureManager::TextureId GenerateUniqueTextureId();
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
299 int GetCacheIndexFromId( TextureId textureId );
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.
311 TextureHash GenerateHash( const std::string& url, const ImageDimensions size,
312 const FittingMode::Type fittingMode,
313 const Dali::SamplingMode::Type samplingMode, const UseAtlas useAtlas );
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.
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 );
333 * Undefined copy constructor.
335 TextureManager( const TextureManager& );
338 * Undefined assignment operator.
340 TextureManager& operator=( const TextureManager& rhs );
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
347 void ObserverDestroyed( TextureUploadObserver* observer );
349 private: // Member Variables:
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
364 } // namespace Toolkit
368 #endif // DALI_TOOLKIT_TEXTURE_MANAGER_H