Add multiple thread support to TextureManager
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / texture-manager.h
index a650384..090846e 100644 (file)
  */
 
 // EXTERNAL INCLUDES
+#include <deque>
+#include <functional>
 #include <string>
 #include <dali/public-api/common/dali-vector.h>
 #include <dali/public-api/object/ref-object.h>
 #include <dali/public-api/rendering/texture-set.h>
 #include <dali/devel-api/common/owner-container.h>
-#include <deque>
+#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/image-loader/async-image-loader-devel.h>
 #include <dali-toolkit/devel-api/image-loader/image-atlas.h>
 #include <dali-toolkit/public-api/image-loader/async-image-loader.h>
 #include <dali-toolkit/internal/visuals/texture-upload-observer.h>
 #include <dali-toolkit/internal/visuals/visual-url.h>
+#include <dali-toolkit/internal/helpers/round-robin-container-view.h>
+#include <dali-toolkit/internal/image-loader/async-image-loader-impl.h>
 
 
 namespace Dali
@@ -67,12 +72,12 @@ public:
   };
 
   /**
-   * Whether the texture should be stored in CPU memory, or uploaded to a GPU texture
+   * Whether the pixel data should be kept in TextureManager, or uploaded for rendering
    */
   enum StorageType
   {
-    CPU,
-    GPU_UPLOAD
+    KEEP_PIXEL_BUFFER,
+    UPLOAD_TO_TEXTURE
   };
 
   /**
@@ -140,8 +145,8 @@ public:
 
   /**
    * @brief Requests an image load of the given URL, when the texture has
-   * have loaded, it will perform a CPU blend with the image mask, and upload
-   * the blend texture.
+   * have loaded, it will perform a blend with the image mask, and upload
+   * the blended texture.
    *
    * The parameters are used to specify how the image is loaded.
    * The observer has the UploadComplete method called when the load is ready.
@@ -149,21 +154,26 @@ public:
    * When the client has finished with the Texture, Remove() should be called.
    *
    * @param[in] url               The URL of the image to load
+   * @param[in] maskTextureId     The texture id of an image to mask this with (can be INVALID if no masking required)
+   * @param[in] contentScale      The scale factor to apply to the image before masking
    * @param[in] desiredSize       The size the image is likely to appear at. This can be set to 0,0 for automatic
    * @param[in] fittingMode       The FittingMode to use
    * @param[in] samplingMode      The SamplingMode to use
    * @param[in] useAtlasing       Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be loaded, and marked successful,
    *                              but "useAtlasing" will be set to false in the "UploadCompleted" callback from the TextureManagerUploadObserver.
+   * @param[in] cropToMask        Only used with masking, this will crop the scaled image to the mask size. If false, then the mask will be scaled to fit the image before being applied.
    * @param[in] observer          The client object should inherit from this and provide the "UploadCompleted" virtual.
    *                              This is called when an image load completes (or fails).
    * @return                      A TextureId to use as a handle to reference this Texture
    */
   TextureId RequestLoad( const VisualUrl&         url,
                          TextureId                maskTextureId,
+                         float                    contentScale,
                          const ImageDimensions    desiredSize,
                          FittingMode::Type        fittingMode,
                          Dali::SamplingMode::Type samplingMode,
                          const UseAtlas           useAtlasing,
+                         bool                     cropToMask,
                          TextureUploadObserver*   observer );
 
   /**
@@ -183,6 +193,11 @@ public:
   void Remove( const TextureManager::TextureId textureId );
 
   /**
+   * Get the visualUrl associated with the texture id
+   */
+  const VisualUrl& GetVisualUrl( TextureId textureId );
+
+  /**
    * @brief Get the current state of a texture
    * @param[in] textureId The texture id to query
    * @return The loading state if the texture is valid, or NOT_STARTED if the textureId
@@ -211,23 +226,27 @@ private:
    *
    * @param[in] url               The URL of the image to load
    * @param[in] maskTextureId     The texture id of an image to use as a mask. If no mask is required, then set to INVALID_TEXTURE_ID
+   * @param[in] contentScale      The scaling factor to apply to the content when masking
    * @param[in] desiredSize       The size the image is likely to appear at. This can be set to 0,0 for automatic
    * @param[in] fittingMode       The FittingMode to use
    * @param[in] samplingMode      The SamplingMode to use
    * @param[in] useAtlasing       Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be loaded, and marked successful,
    *                              but "useAtlasing" will be set to false in the "UploadCompleted" callback from the TextureManagerUploadObserver.
+   * @param[in] cropToMask        Whether to crop the target after masking, or scale the mask to the image before masking.
    * @param[in] storageType,      Whether the pixel data is stored in the cache or uploaded to the GPU
    * @param[in] observer          The client object should inherit from this and provide the "UploadCompleted" virtual.
    *                              This is called when an image load completes (or fails).
    * @return                      A TextureId to use as a handle to reference this Texture
    */
-  TextureId RequestInternalLoad(
+  TextureId RequestLoadInternal(
     const VisualUrl&         url,
     TextureId                maskTextureId,
+    float                    contentScale,
     const ImageDimensions    desiredSize,
     FittingMode::Type        fittingMode,
     Dali::SamplingMode::Type samplingMode,
     UseAtlas                 useAtlas,
+    bool                     cropToMask,
     StorageType              storageType,
     TextureUploadObserver*   observer );
 
@@ -243,9 +262,11 @@ private:
                  TextureId maskTextureId,
                  const VisualUrl& url,
                  ImageDimensions desiredSize,
+                 float scaleFactor,
                  FittingMode::Type fittingMode,
                  Dali::SamplingMode::Type samplingMode,
                  bool loadSynchronously,
+                 bool cropToMask,
                  UseAtlas useAtlas,
                  TextureManager::TextureHash hash )
     : url( url ),
@@ -255,13 +276,15 @@ private:
       textureId( textureId ),
       maskTextureId( maskTextureId ),
       hash( hash ),
+      scaleFactor( scaleFactor ),
       referenceCount( 1u ),
       loadState( NOT_STARTED ),
       fittingMode( fittingMode ),
       samplingMode( samplingMode ),
-      storageType( GPU_UPLOAD ),
+      storageType( UPLOAD_TO_TEXTURE ),
       loadSynchronously( loadSynchronously ),
-      useAtlas( useAtlas )
+      useAtlas( useAtlas ),
+      cropToMask( cropToMask )
     {
     }
 
@@ -272,7 +295,7 @@ private:
 
     ObserverListType observerList; ///< Container used to store all observer clients of this Texture
     Toolkit::ImageAtlas atlas;     ///< The atlas this Texture lays within (if any)
-    PixelData pixelData;           ///< The PixelData holding the image data (this is used if atlasing is deferred or CPU storage is required)
+    Devel::PixelBuffer pixelBuffer;///< The PixelBuffer holding the image data (May be empty after upload)
     TextureSet textureSet;         ///< The TextureSet holding the Texture
     VisualUrl url;                 ///< The URL of the image
     ImageDimensions desiredSize;   ///< The size requested
@@ -281,6 +304,7 @@ private:
     TextureId textureId;           ///< The TextureId associated with this Texture
     TextureId maskTextureId;       ///< The mask TextureId to be applied on load
     TextureManager::TextureHash hash; ///< The hash used to cache this Texture
+    float scaleFactor;             ///< The scale factor to apply to the Texture when masking
     int16_t referenceCount;        ///< The reference count of clients using this Texture
     LoadState loadState:3;         ///< The load state showing the load progress of the Texture
     FittingMode::Type fittingMode:2; ///< The requested FittingMode
@@ -288,6 +312,7 @@ private:
     StorageType storageType:1;     ///< CPU storage / GPU upload;
     bool loadSynchronously:1;      ///< True if synchronous loading was requested
     UseAtlas useAtlas:1;           ///< USE_ATLAS if an atlas was requested. This is updated to false if atlas is not used
+    bool cropToMask:1;             ///< true if the image should be cropped to the mask size.
   };
 
   // Structs:
@@ -346,32 +371,32 @@ private:
   /**
    * @brief This signal handler is called when the async local loader finishes loading.
    * @param[in] id        This is the async image loaders Id
-   * @param[in] pixelData The loaded image data
+   * @param[in] pixelBuffer The loaded image data
    */
-  void AsyncLocalLoadComplete( uint32_t id, PixelData pixelData );
+  void AsyncLocalLoadComplete( uint32_t id, Devel::PixelBuffer pixelBuffer );
 
   /**
    * @brief This signal handler is called when the async local loader finishes loading.
    * @param[in] id        This is the async image loaders Id
-   * @param[in] pixelData The loaded image data
+   * @param[in] pixelBuffer The loaded image data
    */
-  void AsyncRemoteLoadComplete( uint32_t id, PixelData pixelData );
+  void AsyncRemoteLoadComplete( uint32_t id, Devel::PixelBuffer pixelBuffer );
 
   /**
    * Common method to handle loading completion
    * @param[in] container The Async loading container
    * @param[in] id        This is the async image loaders Id
-   * @param[in] pixelData The loaded image data
+   * @param[in] pixelBuffer The loaded image data
    */
-  void AsyncLoadComplete( AsyncLoadingInfoContainerType& container, uint32_t id, PixelData pixelData );
+  void AsyncLoadComplete( AsyncLoadingInfoContainerType& container, uint32_t id, Devel::PixelBuffer pixelBuffer );
 
   /**
    * @brief Performs Post-Load steps including atlasing.
    * @param[in] textureInfo The struct associated with this Texture
-   * @param[in] pixelData   The image pixelData
+   * @param[in] pixelBuffer The image pixelBuffer
    * @return    True if successful
    */
-  void PostLoad( TextureManager::TextureInfo& textureInfo, PixelData pixelData );
+  void PostLoad( TextureManager::TextureInfo& textureInfo, Devel::PixelBuffer& pixelBuffer );
 
   /**
    * Check if there is a texture waiting to be masked. If there
@@ -381,19 +406,22 @@ private:
   void CheckForWaitingTexture( TextureInfo& maskTextureInfo );
 
   /**
-   * Apply the mask texture to the image texture.
-   * @param[in] pixelData The image pixelData to apply the mask to
+   * Apply the mask to the pixelBuffer.
+   * @param[in] pixelBuffer The pixelBuffer to apply the mask to
    * @param[in] maskTextureId The texture id of the mask.
+   * @param[in] contentScale The factor to scale the content
+   * @param[in] cropToMask Whether to crop the content to the mask size
    */
-  void ApplyMask( PixelData pixelData, TextureId maskTextureId );
+  void ApplyMask( Devel::PixelBuffer& pixelBuffer, TextureId maskTextureId,
+                  float contentScale, bool cropToMask );
 
   /**
-   * Upload the texture specified in pixelData to the appropriate location
-   * @param[in] pixelData The image data to upload
+   * Upload the texture specified in pixelBuffer to the appropriate location
+   * @param[in] pixelBuffer The image data to upload
    * @param[in] textureInfo The texture info containing the location to
    * store the data to.
    */
-  void UploadTexture( PixelData pixelData, TextureInfo& textureInfo );
+  void UploadTexture( Devel::PixelBuffer& pixelBuffer, TextureInfo& textureInfo );
 
   /**
    * Mark the texture as complete, and inform observers
@@ -440,7 +468,6 @@ private:
                             const FittingMode::Type fittingMode,
                             const Dali::SamplingMode::Type samplingMode, const UseAtlas useAtlas,
                             TextureId maskTextureId );
-
   /**
    * @brief Looks up a cached texture by its hash.
    * If found, the given parameters are used to check there is no hash-collision.
@@ -462,18 +489,75 @@ private:
     const bool useAtlas,
     TextureId maskTextureId );
 
+private:
+
+  /**
+   * @brief Helper class to keep the relation between AsyncImageLoader and corresponding LoadingInfo container
+   */
+  class AsyncLoadingHelper : public ConnectionTracker
+  {
+  public:
+    /**
+     * @brief Create an AsyncLoadingHelper.
+     * @param[in] textureManager Reference to the texture manager
+     */
+    AsyncLoadingHelper(TextureManager& textureManager);
+
+    /**
+     * @brief Load a new texture.
+     * @param[in] textureId             TextureId to reference the texture that will be loaded
+     * @param[in] url                   The URL of the image to load
+     * @param[in] desiredSize           The size the image is likely to appear at. This can be set to 0,0 for automatic
+     * @param[in] fittingMode           The FittingMode to use
+     * @param[in] samplingMode          The SamplingMode to use
+     * @param[in] orientationCorrection Whether to use image metadata to rotate or flip the image, e.g., from portrait to landscape
+     */
+    void Load(TextureId textureId,
+              const VisualUrl& url,
+              ImageDimensions desiredSize,
+              FittingMode::Type fittingMode,
+              SamplingMode::Type samplingMode,
+              bool orientationCorrection);
+
+  public:
+    AsyncLoadingHelper(const AsyncLoadingHelper&) = delete;
+    AsyncLoadingHelper& operator=(const AsyncLoadingHelper&) = delete;
+
+    AsyncLoadingHelper(AsyncLoadingHelper&& rhs);
+    AsyncLoadingHelper& operator=(AsyncLoadingHelper&&rhs) = delete;
+
+  private:
+    /**
+     * @brief Main constructor that used by all other constructors
+     */
+    AsyncLoadingHelper(Toolkit::AsyncImageLoader loader,
+                       TextureManager& textureManager,
+                       AsyncLoadingInfoContainerType&& loadingInfoContainer);
+
+    /**
+     * @brief Callback to be called when texture loading is complete, it passes the pixel buffer on to texture manager.
+     * @param[in] id          Loader id
+     * @param[in] pixelBuffer Image data
+     */
+    void AsyncLoadComplete(uint32_t id, Devel::PixelBuffer pixelBuffer);
+
+  private:
+    Toolkit::AsyncImageLoader     mLoader;
+    TextureManager&               mTextureManager;
+    AsyncLoadingInfoContainerType mLoadingInfoContainer;
+  };
 
 private:
 
   /**
-   * Undefined copy constructor.
+   * Deleted copy constructor.
    */
-  TextureManager( const TextureManager& );
+  TextureManager( const TextureManager& ) = delete;
 
   /**
-   * Undefined assignment operator.
+   * Deleted assignment operator.
    */
-  TextureManager& operator=( const TextureManager& rhs );
+  TextureManager& operator=( const TextureManager& rhs ) = delete;
 
   /**
    * This is called by the TextureManagerUploadObserver when an observer is destroyed.
@@ -484,14 +568,12 @@ private:
 
 private:  // Member Variables:
 
-  AsyncLoadingInfoContainerType         mAsyncLocalLoadingInfoContainer;     ///< Used to manage Asynchronous loads in progress
-  AsyncLoadingInfoContainerType         mAsyncRemoteLoadingInfoContainer;     ///< Used to manage Asynchronous loads in progress
-  AtlasInfoContainerType                mAtlasContainer;                ///< Used to manage Atlas creation and destruction
-  TextureInfoContainerType              mTextureInfoContainer;          ///< Used to manage the life-cycle and caching of Textures
-  Toolkit::AsyncImageLoader             mAsyncLocalLoader;              ///< The Asynchronous image loader used to provide all local async loads
-  Toolkit::AsyncImageLoader             mAsyncRemoteLoader;             ///< The Asynchronous image loader used to provide all remote async loads
-  TextureId                             mCurrentTextureId;              ///< The current value used for the unique Texture Id generation
+  AtlasInfoContainerType        mAtlasContainer;                  ///< Used to manage Atlas creation and destruction
+  TextureInfoContainerType      mTextureInfoContainer;            ///< Used to manage the life-cycle and caching of Textures
+  TextureId                     mCurrentTextureId;                ///< The current value used for the unique Texture Id generation
 
+  RoundRobinContainerView<AsyncLoadingHelper> mAsyncLocalLoaders;  ///< The Asynchronous image loaders used to provide all local async loads
+  RoundRobinContainerView<AsyncLoadingHelper> mAsyncRemoteLoaders; ///< The Asynchronous image loaders used to provide all remote async loads
 };