1 #ifndef DALI_TOOLKIT_TEXTURE_MANAGER_IMPL_H
2 #define DALI_TOOLKIT_TEXTURE_MANAGER_IMPL_H
5 * Copyright (c) 2021 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.
21 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
22 #include <dali/devel-api/common/owner-container.h>
23 #include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
24 #include <dali/public-api/common/dali-vector.h>
25 #include <dali/public-api/object/ref-object.h>
26 #include <dali/public-api/rendering/geometry.h>
27 #include <dali/public-api/rendering/texture-set.h>
34 #include <dali-toolkit/devel-api/image-loader/async-image-loader-devel.h>
35 #include <dali-toolkit/devel-api/image-loader/image-atlas.h>
36 #include <dali-toolkit/internal/helpers/round-robin-container-view.h>
37 #include <dali-toolkit/internal/image-loader/async-image-loader-impl.h>
38 #include <dali-toolkit/internal/visuals/texture-upload-observer.h>
39 #include <dali-toolkit/internal/visuals/visual-url.h>
40 #include <dali-toolkit/public-api/image-loader/async-image-loader.h>
48 class ImageAtlasManager;
49 typedef IntrusivePtr<ImageAtlasManager> ImageAtlasManagerPtr;
52 * The TextureManager provides a common Image loading API for Visuals.
54 * The TextureManager is responsible for providing sync, async, atlased and non-atlased loads.
55 * Texture caching is provided and performed when possible.
56 * Broken Images are automatically provided on load failure.
58 class TextureManager : public ConnectionTracker
61 typedef int32_t TextureId; ///< The TextureId type. This is used as a handle to refer to a particular Texture.
62 static const int INVALID_TEXTURE_ID = -1; ///< Used to represent a null TextureId or error
65 * Whether the texture should be atlased or uploaded into it's own GPU texture
74 * Whether the pixel data should be kept in TextureManager, returned with pixelBuffer or uploaded for rendering
76 enum class StorageType : uint8_t
78 KEEP_PIXEL_BUFFER, ///< Keep loaded pixel buffer inside of texture manager without making texture. This could be used for inside pixel process like mask image.
79 RETURN_PIXEL_BUFFER, ///< Return loaded pixel buffer without making texture.
80 /// Because a pixel buffer cannot be used multiple texture, this pixel buffer only cached during loading, and is removed after loading is finished.
81 UPLOAD_TO_TEXTURE ///< Loaded image will be uploaded to texture and the texture will be returned.
85 * Whether the texture should be loaded synchronously or asynchronously.
87 enum class LoadType : uint8_t
94 * @brief The LoadState Enumeration represents the current state of a particular Texture's life-cycle.
96 enum class LoadState : uint8_t
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
110 * @brief Types of reloading policies
112 enum class ReloadPolicy
114 CACHED = 0, ///< Loads cached texture if it exists.
115 FORCED ///< Forces reloading of texture.
119 * @brief Whether to multiply alpha into color channels on load
121 enum class MultiplyOnLoad
123 LOAD_WITHOUT_MULTIPLY = 0, ///< Don't modify the image
124 MULTIPLY_ON_LOAD ///< Multiply alpha into color channels on load
131 ~MaskingData() = default;
133 VisualUrl mAlphaMaskUrl;
134 TextureManager::TextureId mAlphaMaskId;
135 float mContentScaleFactor;
138 using MaskingDataPointer = std::unique_ptr<MaskingData>;
141 * Class to provide lifecycle event on destruction of texture manager.
143 struct LifecycleObserver
146 * Called shortly before the texture manager is destroyed.
148 virtual void TextureManagerDestroyed() = 0;
159 ~TextureManager() override;
161 // TextureManager Main API:
164 * @brief Requests an frame of animated image load.
166 * The parameters are used to specify how the animated image is loaded.
167 * The observer has the LoadComplete method called when the load is ready.
169 * @param[in] animatedImageLoading The AnimatedImageLoading that contain the animated image information
170 * @param[in] frameIndex The frame index to load.
171 * @param[in] samplingMode The SamplingMode to use
172 * @param[in] synchronousLoading true if the frame should be loaded synchronously
173 * @param[out] textureId The textureId of the frame
174 * @param[in] wrapModeU Horizontal Wrap mode
175 * @param[in] wrapModeV Vertical Wrap mode
176 * @param[in] textureObserver The client object should inherit from this and provide the "UploadCompleted" virtual.
177 * This is called when an image load completes (or fails).
179 * @return The texture set containing the frame of animated image, or empty if still loading.
181 TextureSet LoadAnimatedImageTexture(Dali::AnimatedImageLoading animatedImageLoading,
183 Dali::SamplingMode::Type samplingMode,
184 bool synchronousLoading,
185 TextureManager::TextureId& textureId,
186 Dali::WrapMode::Type wrapModeU,
187 Dali::WrapMode::Type wrapModeV,
188 TextureUploadObserver* textureObserver);
191 * @brief Requests an image load of the given URL to get PixelBuffer.
193 * The parameters are used to specify how the image is loaded.
194 * The observer has the LoadComplete method called when the load is ready.
196 * @param[in] url The URL of the image to load
197 * @param[in] desiredSize The size the image is likely to appear at. This can be set to 0,0 for automatic
198 * @param[in] fittingMode The FittingMode to use
199 * @param[in] samplingMode The SamplingMode to use
200 * @param[in] synchronousLoading true if the URL should be loaded synchronously
201 * @param[in] textureObserver The client object should inherit from this and provide the "UploadCompleted" virtual.
202 * This is called when an image load completes (or fails).
203 * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data
204 * @param[in,out] preMultiplyOnLoad True if the image color should be multiplied by it's alpha. Set to false if the
205 * image has no alpha channel
207 * @return The pixel buffer containing the image, or empty if still loading.
209 Devel::PixelBuffer LoadPixelBuffer(const VisualUrl& url,
210 Dali::ImageDimensions desiredSize,
211 Dali::FittingMode::Type fittingMode,
212 Dali::SamplingMode::Type samplingMode,
213 bool synchronousLoading,
214 TextureUploadObserver* textureObserver,
215 bool orientationCorrection,
216 TextureManager::MultiplyOnLoad& preMultiplyOnLoad);
219 * @brief Requests an image load of the given URL.
221 * The parameters are used to specify how the image is loaded.
222 * The observer has the UploadComplete method called when the load is ready.
224 * When the client has finished with the Texture, Remove() should be called.
226 * @param[in] url The URL of the image to load
227 * @param[in] desiredSize The size the image is likely to appear at. This can be set to 0,0 for automatic
228 * @param[in] fittingMode The FittingMode to use
229 * @param[in] samplingMode The SamplingMode to use
230 * @param[in, out] maskInfo Mask info structure
231 * @param[in] synchronousLoading true if the URL should be loaded synchronously
232 * @param[out] textureId, The textureId of the URL
233 * @param[out] textureRect The rectangle within the texture atlas that this URL occupies,
234 * this is the rectangle in normalized coordinates.
235 * @param[out] textureRectSize The rectangle within the texture atlas that this URL occupies,
236 * this is the same rectangle in pixels.
237 * @param[in,out] atlasingStatus Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still
238 * be loaded, and marked successful, but this will be set to false.
239 * If atlasing succeeds, this will be set to true.
240 * @param[out] loadingStatus The loading status of the texture
241 * @param[in] wrapModeU Horizontal Wrap mode
242 * @param[in] wrapModeV Vertical Wrap mode
243 * @param[in] textureObserver The client object should inherit from this and provide the "UploadCompleted" virtual.
244 * This is called when an image load completes (or fails).
245 * @param[in] atlasObserver This is used if the texture is atlased, and will be called instead of
246 * textureObserver.UploadCompleted
247 * @param[in] imageAtlasManager The atlas manager to use for atlasing textures
248 * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data
249 * @param[in] reloadPolicy Forces a reload of the texture even if already cached
250 * @param[in,out] preMultiplyOnLoad True if the image color should be multiplied by it's alpha. Set to false if the
251 * image has no alpha channel
253 * @return The texture set containing the image, or empty if still loading.
255 TextureSet LoadTexture(const VisualUrl& url,
256 Dali::ImageDimensions desiredSize,
257 Dali::FittingMode::Type fittingMode,
258 Dali::SamplingMode::Type samplingMode,
259 MaskingDataPointer& maskInfo,
260 bool synchronousLoading,
261 TextureManager::TextureId& textureId,
262 Vector4& textureRect,
263 Dali::ImageDimensions& textureRectSize,
264 bool& atlasingStatus,
266 Dali::WrapMode::Type wrapModeU,
267 Dali::WrapMode::Type wrapModeV,
268 TextureUploadObserver* textureObserver,
269 AtlasUploadObserver* atlasObserver,
270 ImageAtlasManagerPtr imageAtlasManager,
271 bool orientationCorrection,
272 TextureManager::ReloadPolicy reloadPolicy,
273 MultiplyOnLoad& preMultiplyOnLoad);
276 * @brief Requests an image load of the given URL.
278 * The parameters are used to specify how the image is loaded.
279 * The observer has the UploadComplete method called when the load is ready.
281 * When the client has finished with the Texture, Remove() should be called.
283 * @param[in] url The URL of the image to load
284 * @param[in] desiredSize The size the image is likely to appear at. This can be set to 0,0 for automatic
285 * @param[in] fittingMode The FittingMode to use
286 * @param[in] samplingMode The SamplingMode to use
287 * @param[in] useAtlasing Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be loaded, and marked successful,
288 * but "useAtlasing" will be set to false in the "UploadCompleted" callback from the TextureManagerUploadObserver.
289 * @param[in] observer The client object should inherit from this and provide the "UploadCompleted" virtual.
290 * This is called when an image load completes (or fails).
291 * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data
292 * @param[in] reloadPolicy Forces a reload of the texture even if already cached
293 * @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
294 * @param[in] synchronousLoading true if the frame should be loaded synchronously
295 * @return A TextureId to use as a handle to reference this Texture
297 TextureId RequestLoad(const VisualUrl& url,
298 const ImageDimensions desiredSize,
299 FittingMode::Type fittingMode,
300 Dali::SamplingMode::Type samplingMode,
301 const UseAtlas useAtlasing,
302 TextureUploadObserver* observer,
303 bool orientationCorrection,
304 TextureManager::ReloadPolicy reloadPolicy,
305 MultiplyOnLoad& preMultiplyOnLoad,
306 bool synchronousLoading = false);
309 * @brief Requests an image load of the given URL, when the texture has
310 * have loaded, it will perform a blend with the image mask, and upload
311 * the blended texture.
313 * The parameters are used to specify how the image is loaded.
314 * The observer has the UploadComplete method called when the load is ready.
316 * When the client has finished with the Texture, Remove() should be called.
318 * @param[in] url The URL of the image to load
319 * @param[in] maskTextureId The texture id of an image to mask this with
320 * (can be INVALID if no masking required)
321 * @param[in] contentScale The scale factor to apply to the image before masking
322 * @param[in] desiredSize The size the image is likely to appear at. This can be set to 0,0 for automatic
323 * @param[in] fittingMode The FittingMode to use
324 * @param[in] samplingMode The SamplingMode to use
325 * @param[in] useAtlasing Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still
326 * be loaded, and marked successful,
327 * but "useAtlasing" will be set to false in the "UploadCompleted" callback from
328 * the TextureManagerUploadObserver.
329 * @param[in] cropToMask Only used with masking, this will crop the scaled image to the mask size.
330 * If false, then the mask will be scaled to fit the image before being applied.
331 * @param[in] observer The client object should inherit from this and provide the "UploadCompleted"
333 * This is called when an image load completes (or fails).
334 * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data
335 * @param[in] reloadPolicy Forces a reload of the texture even if already cached
336 * @param[in] preMultiplyOnLoad True if the image color should be multiplied by it's alpha. Set to false if the
337 * image has no alpha channel
338 * @param[in] synchronousLoading true if the frame should be loaded synchronously
339 * @return A TextureId to use as a handle to reference this Texture
341 TextureId RequestLoad(const VisualUrl& url,
342 TextureId maskTextureId,
344 const ImageDimensions desiredSize,
345 FittingMode::Type fittingMode,
346 Dali::SamplingMode::Type samplingMode,
347 const UseAtlas useAtlasing,
349 TextureUploadObserver* observer,
350 bool orientationCorrection,
351 TextureManager::ReloadPolicy reloadPolicy,
352 MultiplyOnLoad& preMultiplyOnLoad,
353 bool synchronousLoading = false);
356 * Requests a masking image to be loaded. This mask is not uploaded to GL,
357 * instead, it is stored in CPU memory, and can be used for CPU blending.
359 TextureId RequestMaskLoad(const VisualUrl& maskUrl,
360 bool synchronousLoading = false);
363 * @brief Remove a Texture from the TextureManager.
365 * Textures are cached and therefore only the removal of the last
366 * occurrence of a Texture will cause its removal internally.
368 * @param[in] textureId The ID of the Texture to remove.
369 * @param[in] textureObserver The texture observer.
371 void Remove(const TextureManager::TextureId textureId, TextureUploadObserver* textureObserver);
374 * @brief Get the visualUrl associated with the texture id.
375 * @param[in] textureId The texture Id to get
376 * @return The visual Url associated with the texture id.
378 VisualUrl GetVisualUrl(TextureId textureId);
381 * @brief Get the current state of a texture
382 * @param[in] textureId The texture id to query
383 * @return The loading state if the texture is valid, or NOT_STARTED if the textureId
386 LoadState GetTextureState(TextureId textureId);
389 * @brief Get the associated texture set if the texture id is valid
390 * @param[in] textureId The texture Id to look up
391 * @return the associated texture set, or an empty handle if textureId is not valid
393 TextureSet GetTextureSet(TextureId textureId);
396 * @brief Get the encoded image buffer
397 * @param[in] textureId The textureId to look up
398 * @return the encoded image buffer, or an empty handle if textureId is not valid
400 EncodedImageBuffer GetEncodedImageBuffer(TextureId textureId);
403 * @brief Get the encoded image buffer by VisualUrl
404 * @param[in] url The url to look up
405 * @return the encoded image buffer, or an empty handle if url is not buffer resource or buffer is not valid
407 EncodedImageBuffer GetEncodedImageBuffer(const std::string& url);
410 * Adds an external texture to the texture manager
411 * @param[in] texture The texture to add
412 * @return string containing the URL for the texture
414 std::string AddExternalTexture(TextureSet& texture);
417 * Adds an external encoded image buffer to the texture manager
418 * @param[in] encodedImageBuffer The image buffer to add
419 * @return string containing the URL for the texture
421 std::string AddExternalEncodedImageBuffer(const EncodedImageBuffer& encodedImageBuffer);
424 * Removes an external texture from texture manager
425 * @param[in] url The string containing the texture to remove
426 * @return handle to the texture
428 TextureSet RemoveExternalTexture(const std::string& url);
431 * Removes an external encoded image buffer from texture manager
432 * @param[in] url The string containing the encoded image buffer to remove
433 * @return handle to the encoded image buffer
435 EncodedImageBuffer RemoveExternalEncodedImageBuffer(const std::string& url);
438 * @brief Notify that external textures or external encoded image buffers are used.
439 * @param[in] url The URL of the texture to use.
441 void UseExternalResource(const VisualUrl& url);
444 * Add an observer to the object.
445 * @param[in] observer The observer to add.
447 void AddObserver(TextureManager::LifecycleObserver& observer);
450 * Remove an observer from the object
451 * @pre The observer has already been added.
452 * @param[in] observer The observer to remove.
454 void RemoveObserver(TextureManager::LifecycleObserver& observer);
457 * @brief Returns the geometry associated with texture.
458 * @param[in] textureId Id of the texture
459 * @param[out] frontElements number of front elements
460 * @param[out] backElements number of back elements
461 * @return Returns valid geometry object
463 Geometry GetRenderGeometry(TextureId textureId, uint32_t& frontElements, uint32_t& backElements);
467 * @brief Requests an image load of the given URL, when the texture has
468 * have loaded, if there is a valid maskTextureId, it will perform a
469 * CPU blend with the mask, and upload the blend texture.
471 * The parameters are used to specify how the image is loaded.
472 * The observer has the UploadComplete method called when the load is ready.
474 * When the client has finished with the Texture, Remove() should be called.
476 * @param[in] url The URL of the image to load
477 * @param[in] maskTextureId The texture id of an image to use as a mask. If no mask is required, then set
478 * to INVALID_TEXTURE_ID
479 * @param[in] contentScale The scaling factor to apply to the content when masking
480 * @param[in] desiredSize The size the image is likely to appear at. This can be set to 0,0 for automatic
481 * @param[in] fittingMode The FittingMode to use
482 * @param[in] samplingMode The SamplingMode to use
483 * @param[in] useAtlasing Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be
484 * loaded, and marked successful, but "useAtlasing" will be set to false in the
485 * "UploadCompleted" callback from the TextureManagerUploadObserver.
486 * @param[in] cropToMask Whether to crop the target after masking, or scale the mask to the image before
488 * @param[in] storageType, Whether the pixel data is stored in the cache or uploaded to the GPU
489 * @param[in] observer The client object should inherit from this and provide the "UploadCompleted"
491 * This is called when an image load completes (or fails).
492 * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data
493 * @param[in] reloadPolicy Forces a reload of the texture even if already cached
494 * @param[in] preMultiplyOnLoad True if the image color should be multiplied by it's alpha. Set to false if
496 * @param[in] animatedImageLoading The AnimatedImageLoading to load animated image
497 * @param[in] frameIndex The frame index of a frame to be loaded frame
498 * @param[in] synchronousLoading true if the frame should be loaded synchronously
499 * @return A TextureId to use as a handle to reference this Texture
501 TextureId RequestLoadInternal(
502 const VisualUrl& url,
503 TextureId maskTextureId,
505 const ImageDimensions desiredSize,
506 FittingMode::Type fittingMode,
507 Dali::SamplingMode::Type samplingMode,
510 StorageType storageType,
511 TextureUploadObserver* observer,
512 bool orientationCorrection,
513 TextureManager::ReloadPolicy reloadPolicy,
514 MultiplyOnLoad& preMultiplyOnLoad,
515 Dali::AnimatedImageLoading animatedImageLoading,
517 bool synchronousLoading);
520 * @brief Get the current state of a texture
521 * @param[in] textureId The texture id to query
522 * @return The loading state if the texture is valid, or NOT_STARTED if the textureId
525 LoadState GetTextureStateInternal(TextureId textureId);
528 * @brief Load a new image synchronously.
529 * @param[in] url The URL of the image to load
530 * @param[in] desiredSize The size the image is likely to appear at.
531 * This can be set to 0,0 for automatic
532 * @param[in] fittingMode The FittingMode to use
533 * @param[in] samplingMode The SamplingMode to use
534 * @param[in] orientationCorrection Whether to use image metadata to rotate or flip the image,
535 * e.g., from portrait to landscape
536 * @return PixelBuffer of loaded image.
538 Devel::PixelBuffer LoadImageSynchronously(const VisualUrl& url,
539 const ImageDimensions desiredSize,
540 FittingMode::Type fittingMode,
541 Dali::SamplingMode::Type samplingMode,
542 bool orientationCorrection);
544 typedef size_t TextureHash; ///< The type used to store the hash used for Texture caching.
549 * @brief This struct is used to manage the life-cycle of Texture loading and caching.
553 TextureInfo(TextureId textureId,
554 TextureId maskTextureId,
555 const VisualUrl& url,
556 ImageDimensions desiredSize,
558 FittingMode::Type fittingMode,
559 Dali::SamplingMode::Type samplingMode,
560 bool loadSynchronously,
563 TextureManager::TextureHash hash,
564 bool orientationCorrection,
565 bool preMultiplyOnLoad,
566 Dali::AnimatedImageLoading animatedImageLoading,
569 desiredSize(desiredSize),
570 useSize(desiredSize),
571 atlasRect(0.0f, 0.0f, 1.0f, 1.0f), // Full atlas rectangle
572 textureId(textureId),
573 maskTextureId(maskTextureId),
575 scaleFactor(scaleFactor),
577 loadState(LoadState::NOT_STARTED),
578 fittingMode(fittingMode),
579 samplingMode(samplingMode),
580 storageType(StorageType::UPLOAD_TO_TEXTURE),
581 animatedImageLoading(animatedImageLoading),
582 frameIndex(frameIndex),
583 loadSynchronously(loadSynchronously),
585 cropToMask(cropToMask),
586 orientationCorrection(true),
587 preMultiplyOnLoad(preMultiplyOnLoad),
593 * Container type used to store all observer clients of this Texture
595 typedef Dali::Vector<TextureUploadObserver*> ObserverListType;
597 ObserverListType observerList; ///< Container used to store all observer clients of this Texture
598 Toolkit::ImageAtlas atlas; ///< The atlas this Texture lays within (if any)
599 Devel::PixelBuffer pixelBuffer; ///< The PixelBuffer holding the image data (May be empty after upload)
600 TextureSet textureSet; ///< The TextureSet holding the Texture
601 VisualUrl url; ///< The URL of the image
602 ImageDimensions desiredSize; ///< The size requested
603 ImageDimensions useSize; ///< The size used
604 Vector4 atlasRect; ///< The atlas rect used if atlased
605 TextureId textureId; ///< The TextureId associated with this Texture
606 TextureId maskTextureId; ///< The mask TextureId to be applied on load
607 TextureManager::TextureHash hash; ///< The hash used to cache this Texture
608 float scaleFactor; ///< The scale factor to apply to the Texture when masking
609 int16_t referenceCount; ///< The reference count of clients using this Texture
610 LoadState loadState; ///< The load state showing the load progress of the Texture
611 FittingMode::Type fittingMode : 3; ///< The requested FittingMode
612 Dali::SamplingMode::Type samplingMode : 3; ///< The requested SamplingMode
613 StorageType storageType; ///< CPU storage / GPU upload;
614 Dali::AnimatedImageLoading animatedImageLoading; ///< AnimatedImageLoading that contains animated image information.
615 uint32_t frameIndex; ///< frame index that be loaded, in case of animated image
616 bool loadSynchronously : 1; ///< True if synchronous loading was requested
617 UseAtlas useAtlas : 2; ///< USE_ATLAS if an atlas was requested.
618 ///< This is updated to false if atlas is not used
619 bool cropToMask : 1; ///< true if the image should be cropped to the mask size.
620 bool orientationCorrection : 1; ///< true if the image should be rotated to match exif orientation data
621 bool preMultiplyOnLoad : 1; ///< true if the image's color should be multiplied by it's alpha
622 bool preMultiplied : 1; ///< true if the image's color was multiplied by it's alpha
626 * Structure to hold info about a texture load queued during NotifyObservers
628 struct LoadQueueElement
630 LoadQueueElement(TextureId textureId, TextureUploadObserver* observer)
631 : mTextureId(textureId),
636 TextureId mTextureId; ///< The texture id of the requested load.
637 TextureUploadObserver* mObserver; ///< Observer of texture load.
641 * Struct to hold information about a requested Async load.
642 * This is used to look up a TextureManager::TextureId from the returned AsyncLoad Id.
644 struct AsyncLoadingInfo
646 AsyncLoadingInfo(TextureId textureId)
647 : textureId(textureId),
652 TextureId textureId; ///< The external Texture Id assigned to this load
653 uint32_t loadId; ///< The load Id used by the async loader to reference this load
658 typedef std::deque<AsyncLoadingInfo> AsyncLoadingInfoContainerType; ///< The container type used to manage Asynchronous loads in progress
659 typedef std::vector<TextureInfo> TextureInfoContainerType; ///< The container type used to manage the life-cycle and caching of Textures
662 * @brief Initiate a load or queue load if NotifyObservers is invoking callbacks
663 * @param[in] textureInfo The TextureInfo struct associated with the Texture
664 * @param[in] observer The observer wishing to observe the texture upload
666 void LoadOrQueueTexture(TextureInfo& textureInfo, TextureUploadObserver* observer);
669 * @brief Queue a texture load to be subsequently handled by ProcessQueuedTextures.
670 * @param[in] textureInfo The TextureInfo struct associated with the Texture
671 * @param[in] observer The observer wishing to observe the texture upload
673 void QueueLoadTexture(TextureInfo& textureInfo, TextureUploadObserver* observer);
676 * @brief Used internally to initiate a load.
677 * @param[in] textureInfo The TextureInfo struct associated with the Texture
678 * @param[in] observer The observer wishing to observe the texture upload
680 void LoadTexture(TextureInfo& textureInfo, TextureUploadObserver* observer);
683 * @brief Initiate load of textures queued whilst NotifyObservers invoking callbacks.
685 void ProcessQueuedTextures();
688 * Add the observer to the observer list
689 * @param[in] textureInfo The TextureInfo struct associated with the texture
690 * @param[in] observer The observer wishing to observe the texture upload
692 void ObserveTexture(TextureInfo& textureInfo, TextureUploadObserver* observer);
695 * @brief This signal handler is called when the async local loader finishes loading.
696 * @param[in] id This is the async image loaders Id
697 * @param[in] pixelBuffer The loaded image data
699 void AsyncLocalLoadComplete(uint32_t id, Devel::PixelBuffer pixelBuffer);
702 * @brief This signal handler is called when the async local loader finishes loading.
703 * @param[in] id This is the async image loaders Id
704 * @param[in] pixelBuffer The loaded image data
706 void AsyncRemoteLoadComplete(uint32_t id, Devel::PixelBuffer pixelBuffer);
709 * Common method to handle loading completion
710 * @param[in] container The Async loading container
711 * @param[in] id This is the async image loaders Id
712 * @param[in] pixelBuffer The loaded image data
714 void AsyncLoadComplete(AsyncLoadingInfoContainerType& container, uint32_t id, Devel::PixelBuffer pixelBuffer);
717 * @brief Performs Post-Load steps including atlasing.
718 * @param[in] textureInfo The struct associated with this Texture
719 * @param[in] pixelBuffer The image pixelBuffer
720 * @return True if successful
722 void PostLoad(TextureManager::TextureInfo& textureInfo, Devel::PixelBuffer& pixelBuffer);
725 * Check if there is a texture waiting to be masked. If there
726 * is then apply this mask and upload it.
727 * @param[in] maskTextureInfo The texture info of the mask that has just loaded.
729 void CheckForWaitingTexture(TextureInfo& maskTextureInfo);
732 * Apply the mask to the pixelBuffer.
733 * @param[in] textureInfo The information of texture to apply the mask to
734 * @param[in] maskTextureId The texture id of the mask.
736 void ApplyMask(TextureInfo& textureInfo, TextureId maskTextureId);
739 * Upload the texture specified in pixelBuffer to the appropriate location
740 * @param[in] pixelBuffer The image data to upload
741 * @param[in] textureInfo The texture info containing the location to
744 void UploadTexture(Devel::PixelBuffer& pixelBuffer, TextureInfo& textureInfo);
747 * Creates tiled geometry of for the texture which separates fully-opaque
748 * tiles from ones which use transparency.
752 bool CreateTiledGeometry(const Devel::PixelBuffer& pixelBuffer, TextureInfo& textureInfo);
755 * Mark the texture as complete, and inform observers
756 * @param[in] textureInfo The struct associated with this Texture
758 void UploadComplete(TextureInfo& textureInfo);
761 * Notify the current observers that the texture upload is complete,
762 * then remove the observers from the list.
763 * @param[in] textureInfo The struct associated with this Texture
764 * @param[in] success If the pixel data was retrieved successfully and uploaded to GPU
766 void NotifyObservers(TextureInfo& textureInfo, bool success);
769 * @brief Generates a new, unique TextureId
770 * @return A unique TextureId
772 TextureManager::TextureId GenerateUniqueTextureId();
775 * @brief Used to lookup an index into the TextureInfoContainer from a TextureId
776 * @param[in] textureId The TextureId to look up
777 * @return The cache index
779 int GetCacheIndexFromId(TextureId textureId);
782 * @brief Generates a hash for caching based on the input parameters.
783 * Only applies size, fitting mode andsampling mode if the size is specified.
784 * Only applies maskTextureId if it isn't INVALID_TEXTURE_ID
785 * Always applies useAtlas.
786 * @param[in] url The URL of the image to load
787 * @param[in] size The image size
788 * @param[in] fittingMode The FittingMode to use
789 * @param[in] samplingMode The SamplingMode to use
790 * @param[in] useAtlas True if atlased
791 * @param[in] maskTextureId The masking texture id (or INVALID_TEXTURE_ID)
792 * @return A hash of the provided data for caching.
794 TextureHash GenerateHash(const std::string& url, const ImageDimensions size, const FittingMode::Type fittingMode, const Dali::SamplingMode::Type samplingMode, const UseAtlas useAtlas, TextureId maskTextureId);
797 * @brief Looks up a cached texture by its hash.
798 * If found, the given parameters are used to check there is no hash-collision.
799 * @param[in] hash The hash to look up
800 * @param[in] url The URL of the image to load
801 * @param[in] size The image size
802 * @param[in] fittingMode The FittingMode to use
803 * @param[in] samplingMode The SamplingMode to use
804 * @param[in] useAtlas True if atlased
805 * @param[in] maskTextureId Optional texture ID to use to mask this image
806 * @param[in] preMultiplyOnLoad if the image's color should be multiplied by it's alpha. Set to OFF if there is no alpha.
807 * @return A TextureId of a cached Texture if found. Or INVALID_TEXTURE_ID if not found.
809 TextureManager::TextureId FindCachedTexture(
810 const TextureManager::TextureHash hash,
811 const std::string& url,
812 const ImageDimensions size,
813 const FittingMode::Type fittingMode,
814 const Dali::SamplingMode::Type samplingMode,
816 TextureId maskTextureId,
817 MultiplyOnLoad preMultiplyOnLoad);
821 * @brief Helper class to keep the relation between AsyncImageLoader and corresponding LoadingInfo container
823 class AsyncLoadingHelper : public ConnectionTracker
827 * @brief Create an AsyncLoadingHelper.
828 * @param[in] textureManager Reference to the texture manager
830 AsyncLoadingHelper(TextureManager& textureManager);
833 * @brief Load a new frame of animated image
834 * @param[in] textureId TextureId to reference the texture that will be loaded
835 * @param[in] animatedImageLoading The AnimatedImageLoading to load animated image
836 * @param[in] frameIndex The frame index of a frame to be loaded frame
838 void LoadAnimatedImage(TextureId textureId,
839 Dali::AnimatedImageLoading animatedImageLoading,
840 uint32_t frameIndex);
843 * @brief Load a new texture.
844 * @param[in] textureId TextureId to reference the texture that will be loaded
845 * @param[in] url The URL of the image to load
846 * @param[in] desiredSize The size the image is likely to appear at.
847 * This can be set to 0,0 for automatic
848 * @param[in] fittingMode The FittingMode to use
849 * @param[in] samplingMode The SamplingMode to use
850 * @param[in] orientationCorrection Whether to use image metadata to rotate or flip the image,
851 * e.g., from portrait to landscape
852 * @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.
854 void Load(TextureId textureId,
855 const VisualUrl& url,
856 ImageDimensions desiredSize,
857 FittingMode::Type fittingMode,
858 SamplingMode::Type samplingMode,
859 bool orientationCorrection,
860 DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad);
864 * @param [in] id of the texture
865 * @param [in] pixelBuffer of the to be masked image
866 * @param [in] maskPixelBuffer of the mask image
867 * @param [in] contentScale The factor to scale the content
868 * @param [in] cropToMask Whether to crop the content to the mask size
869 * @param [in] preMultiplyOnLoad if the image's color should be multiplied by it's alpha. Set to OFF if there is no alpha.
871 void ApplyMask(TextureId textureId,
872 Devel::PixelBuffer pixelBuffer,
873 Devel::PixelBuffer maskPixelBuffer,
876 DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad);
879 AsyncLoadingHelper(const AsyncLoadingHelper&) = delete;
880 AsyncLoadingHelper& operator=(const AsyncLoadingHelper&) = delete;
882 AsyncLoadingHelper(AsyncLoadingHelper&& rhs);
883 AsyncLoadingHelper& operator=(AsyncLoadingHelper&& rhs) = delete;
887 * @brief Main constructor that used by all other constructors
889 AsyncLoadingHelper(Toolkit::AsyncImageLoader loader,
890 TextureManager& textureManager,
891 AsyncLoadingInfoContainerType&& loadingInfoContainer);
894 * @brief Callback to be called when texture loading is complete, it passes the pixel buffer on to texture manager.
895 * @param[in] id Loader id
896 * @param[in] pixelBuffer Image data
898 void AsyncLoadComplete(uint32_t id, Devel::PixelBuffer pixelBuffer);
901 Toolkit::AsyncImageLoader mLoader;
902 TextureManager& mTextureManager;
903 AsyncLoadingInfoContainerType mLoadingInfoContainer;
906 struct ExternalTextureInfo
909 TextureSet textureSet;
910 int16_t referenceCount{1};
913 struct EncodedBufferTextureInfo
915 EncodedBufferTextureInfo(TextureId textureId,
916 const EncodedImageBuffer& encodedImageBuffer)
917 : textureId(textureId),
918 encodedImageBuffer(encodedImageBuffer),
923 EncodedImageBuffer encodedImageBuffer;
924 int16_t referenceCount;
929 * Deleted copy constructor.
931 TextureManager(const TextureManager&) = delete;
934 * Deleted assignment operator.
936 TextureManager& operator=(const TextureManager& rhs) = delete;
939 * This is called by the TextureManagerUploadObserver when an observer is destroyed.
940 * We use the callback to know when to remove an observer from our notify list.
941 * @param[in] observer The observer that generated the callback
943 void ObserverDestroyed(TextureUploadObserver* observer);
945 private: // Member Variables:
946 TextureInfoContainerType mTextureInfoContainer; ///< Used to manage the life-cycle and caching of Textures
947 RoundRobinContainerView<AsyncLoadingHelper> mAsyncLocalLoaders; ///< The Asynchronous image loaders used to provide all local async loads
948 RoundRobinContainerView<AsyncLoadingHelper> mAsyncRemoteLoaders; ///< The Asynchronous image loaders used to provide all remote async loads
949 std::vector<ExternalTextureInfo> mExternalTextures; ///< Externally provided textures
950 std::vector<EncodedBufferTextureInfo> mEncodedBufferTextures; ///< Externally encoded buffer textures
951 Dali::Vector<LifecycleObserver*> mLifecycleObservers; ///< Lifecycle observers of texture manager
952 Dali::Vector<LoadQueueElement> mLoadQueue; ///< Queue of textures to load after NotifyObservers
953 TextureId mCurrentTextureId; ///< The current value used for the unique Texture Id generation
954 bool mQueueLoadFlag; ///< Flag that causes Load Textures to be queued.
957 } // namespace Internal
959 } // namespace Toolkit
963 #endif // DALI_TOOLKIT_TEXTURE_MANAGER_IMPL_H