1 #ifndef __DALI_TOOLKIT_ATLAS_MANAGER_H__
2 #define __DALI_TOOLKIT_ATLAS_MANAGER_H__
5 * Copyright (c) 2015 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/images/buffer-image.h>
24 #include <dali/devel-api/images/atlas.h>
25 #include <dali/devel-api/rendering/material.h>
33 namespace Internal DALI_INTERNAL
38 } // namespace Internal
44 * Creates and manages additions and removals of images from Texture Atlases
46 * The AtlasManager will match pixeltype and optimal block use to determine
47 * the appropriate atlas to upload an image to.
49 * A policy can be specified to determine the action the AtlasManager will carry
50 * out, should it not be able to add an image. This can return an error, or create
51 * a new atlas of pre-determined dimensions to accomodate the new image.
53 * Images are referenced by an ImageId once they have been successfully uploaded.
55 * Once an image has been successfully uploaded, Geometry can be generated by passing
56 * the ImageId to the GenerateMeshData method and geometry can be consolidated via
57 * the StitchMesh method.
59 * Images are reference counted once mesh data has been generated. An image is removed
60 * from the Atlas via the Remove( ImageId ) method. This unreferences the image and only
61 * physically removes it from the atlas once all references have been freed.
63 * If the AddPolicy is set to generate and error if an image can't be uploaded, then it
64 * is the applications responsibility to deal with the situation. An error will be indicated
65 * with an ImageId of 0.
67 * Examples using the AtlasManager
69 * Create or obtain the AtlasManager
72 * AtlasManager manager = AtlasManager::Get();
76 * Set the AtlasManager AddPolicy
80 * // Tell the atlas manager to create a new atlas, if it needs to
81 * manager.SetAddPolicy( FAIL_ON_ADD_CREATES );
83 * // Tell the atlas manager to return an error, if it can't add an image
84 * manager.SetAddPolicy( FAIL_ON_ADD_FAILS );
88 * Simple add and removal of BufferImage to and from an atlas
92 * // Structure returned by AtlasManager operations
95 * // Add image to an atlas ( will be created if none suitable exists )
96 * manager.Add( bitmapImage, slot );
98 * // slot.mImage returns the imageId for the bitmap, slot.mAtlas indicates the atlasId
99 * // that the image was added to. The imageId is used to communicate with the AtlasManager
100 * uint32_t imageId = slot.mImage;
103 * // Addition has failed.....
107 * // Done with image, so remove from atlas, if not being used elsewhere
108 * manager.Remove( imageId );
112 * Create a Specific Atlas for adding BufferImages to
116 * // Create an RGB888 atlas of 2048x2848, with a blocksize of 128x128
117 * uint32_t atlas = manager.CreateAtlas( 2048u, 2048u, 128u, 128u, Pixel::RGB888 );
119 * // Add an image to a preferred atlas ( note not specifying atlas may still result
120 * // in the bitmap being added to the atlas above )
121 * manager.Add( bitmapImage, slot, atlas );
125 * Create Geometry for a previously added image
129 * // Top left corner of geometry to be generated
130 * Vector2 position( 1.0f, 1.0f );
132 * // Geometry will end up here!
134 * manager.GenerateMeshData( imageId, position, meshData );
138 * Generating Geometry from multiple images in the same atlas
142 * MeshData firstMesh;
143 * MeshData secondMesh;
144 * manager.GenerateMeshData( imageid_1, position_1, firstMesh );
145 * manager.GenerateMeshData( imageid_2, position_2, secondMesh );
147 * // Combine the two meshes. Passing MESH_OPTIMIZE as an optional third parameter will remove duplicate vertices
148 * manager.StitchMesh( first, second );
154 class AtlasManager : public BaseHandle
158 typedef uint32_t SizeType;
159 typedef SizeType AtlasId;
160 typedef SizeType ImageId;
161 static const bool MESH_OPTIMIZE = true;
165 SizeType mWidth; ///< width of the atlas in pixels
166 SizeType mHeight; ///< height of the atlas in pixels
167 SizeType mBlockWidth; ///< width of a block in pixels
168 SizeType mBlockHeight; ///< height of a block in pixels
172 * Metrics structures to describe Atlas Manager state
175 struct AtlasMetricsEntry
177 AtlasSize mSize; ///< size of atlas and blocks
178 SizeType mBlocksUsed; ///< number of blocks used in the atlas
179 SizeType mTotalBlocks; ///< total blocks used by atlas
180 Pixel::Format mPixelFormat; ///< pixel format of the atlas
187 mTextureMemoryUsed( 0u )
193 SizeType mAtlasCount; ///< number of atlases
194 SizeType mTextureMemoryUsed; ///< texture memory used by atlases
195 Dali::Vector< AtlasMetricsEntry > mAtlasMetrics; ///< container of atlas information
206 Vector< Vertex2D > mVertices;
207 Vector< unsigned int> mIndices;
211 * Create an AtlasManager handle; this can be initialised with AtlasManager::New()
212 * Calling member functions with an uninitialised handle is not allowed.
217 * @brief Get new instance of AtlasManager object.
219 * @return A handle to the AtlasManager control.
221 static AtlasManager New();
226 * This is non-virtual since derived Handle types must not contain data or virtual methods.
231 * Policy on failing to add an image
240 * @brief Container to hold result of placing texture into atlas
244 ImageId mImageId; ///< Id of stored Image
245 AtlasId mAtlasId; ///< Id of Atlas containing this slot
248 typedef Dali::Vector< AtlasManager::AtlasSlot > slotContainer;
251 * @brief Create a blank atlas of specific dimensions and pixel format with a certain block size
253 * @param[in] size desired atlas dimensions
254 * @param[in] pixelformat format of a pixel in atlas
258 AtlasId CreateAtlas( const AtlasSize& size, Pixel::Format pixelformat = Pixel::RGBA8888 );
261 * @brief Set the policy on failure to add an image to an atlas
263 * @param policy policy to carry out if add fails
265 void SetAddPolicy( AddFailPolicy policy );
268 * @brief Attempts to add an image to the most suitable atlas
270 * @details Add Policy may dictate that a new atlas is created if it can't presently be placed.
271 * If an add is made before an atlas is created under this policy,
272 * then a default size atlas will be created
274 * @param[in] image reference to a bitmapimage
275 * @param[out] slot result of add operation
276 * @param[in] atlas optional preferred atlas
278 void Add( const BufferImage& image,
283 * @brief Remove previously added bitmapimage from atlas
285 * @param[in] id ImageId returned in the AtlasSlot from the add operation
287 * @return if true then image has been removed from the atlas
289 bool Remove( ImageId id );
292 * @brief Generate mesh data for a previously added image
294 * @param[in] id Image Id returned in the AtlasSlot from the add operation
295 * @param[in] position position of the resulting mesh in model space
296 * @param[out] mesh Mesh Data Object to populate with mesh data
297 * @param[in] addReference Whether to increase the internal reference count for image or not
299 void GenerateMeshData( ImageId id,
300 const Vector2& position,
302 bool addReference = true );
305 * @brief Append second mesh to the first mesh
307 * @param[in] first First mesh
308 * @param[in] second Second mesh
309 * @param[in] optimize should we optimize vertex data
311 void StitchMesh( Mesh2D& first,
312 const Mesh2D& second,
313 bool optimize = false );
316 * @brief Get the BufferImage containing an atlas
318 * @param[in] atlas AtlasId returned when atlas was created
320 * @return Atlas Handle
322 Dali::Atlas GetAtlasContainer( AtlasId atlas ) const;
325 * @brief Get the Id of the atlas containing an image
327 * @param[in] id ImageId
331 AtlasId GetAtlas( ImageId id );
333 * @brief Get the current size of an atlas
335 * @param[in] atlas AtlasId
337 * @return AtlasSize structure for the atlas
339 const AtlasSize& GetAtlasSize( AtlasId atlas );
342 * @brief Get the number of blocks available in an atlas
344 * @param[in] atlas AtlasId
346 * @return Number of blocks free in this atlas
348 SizeType GetFreeBlocks( AtlasId atlas );
351 * @brief Sets the pixel area of any new atlas and also the individual block size
353 * @param[in] size Atlas size structure
355 * @param blockSize pixel area in atlas for a block
357 void SetNewAtlasSize( const AtlasSize& size );
360 * @brief Get the number of atlases created
362 * @return number of atlases
364 SizeType GetAtlasCount() const;
367 * @brief Get the pixel format used by an atlas
369 * @param[in] atlas AtlasId
371 * @return Pixel format used by this atlas
373 Pixel::Format GetPixelFormat( AtlasId atlas );
376 * @brief Fill in a metrics structure showing current status of this Atlas Manager
378 * @param[in] metrics metrics structure to be filled
380 void GetMetrics( Metrics& metrics );
383 * @brief Get Material used by atlas
385 * @param atlas[in] atlas AtlasId
387 * @return Material used by atlas
389 Material GetMaterial( AtlasId atlas ) const;
392 * @brief Get Sampler used by atlas
394 * @param atlas[in] atlas AtlasId
396 * @return Sampler used by atlas
398 Sampler GetSampler( AtlasId atlas ) const;
401 explicit DALI_INTERNAL AtlasManager(Internal::AtlasManager *impl);
405 } // namespace Toolkit
409 #endif // __DALI_TOOLKIT_ATLAS_MANAGER_H__