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
185 SizeType mAtlasCount; // number of atlases
186 SizeType mTextureMemoryUsed; // texture memory used by atlases
187 Dali::Vector< AtlasMetricsEntry > mAtlasMetrics; // container of atlas information
198 Vector< Vertex2D > mVertices;
199 Vector< unsigned int> mIndices;
203 * Create an AtlasManager handle; this can be initialised with AtlasManager::New()
204 * Calling member functions with an uninitialised handle is not allowed.
209 * @brief Get new instance of AtlasManager object.
211 * @return A handle to the AtlasManager control.
213 static AtlasManager New();
218 * This is non-virtual since derived Handle types must not contain data or virtual methods.
223 * Policy on failing to add an image
232 * @brief Container to hold result of placing texture into atlas
236 ImageId mImageId; // Id of stored Image
237 AtlasId mAtlasId; // Id of Atlas containing this slot
240 typedef Dali::Vector< AtlasManager::AtlasSlot > slotContainer;
243 * @brief Create a blank atlas of specific dimensions and pixel format with a certain block size
245 * @param[in] size desired atlas dimensions
246 * @param[in] pixelformat format of a pixel in atlas
250 AtlasId CreateAtlas( const AtlasSize& size, Pixel::Format pixelformat = Pixel::RGBA8888 );
253 * @brief Set the policy on failure to add an image to an atlas
255 * @param policy policy to carry out if add fails
257 void SetAddPolicy( AddFailPolicy policy );
260 * @brief Attempts to add an image to the most suitable atlas
262 * @details Add Policy may dictate that a new atlas is created if it can't presently be placed.
263 * If an add is made before an atlas is created under this policy,
264 * then a default size atlas will be created
266 * @param[in] image reference to a bitmapimage
267 * @param[out] slot result of add operation
268 * @param[in] atlas optional preferred atlas
270 void Add( const BufferImage& image,
275 * @brief Remove previously added bitmapimage from atlas
277 * @param[in] id ImageId returned in the AtlasSlot from the add operation
279 * @return if true then image has been removed from the atlas
281 bool Remove( ImageId id );
284 * @brief Generate mesh data for a previously added image
286 * @param[in] id Image Id returned in the AtlasSlot from the add operation
287 * @param[in] position position of the resulting mesh in model space
288 * @param[out] mesh Mesh Data Object to populate with mesh data
289 * @param[in] addReference Whether to increase the internal reference count for image or not
291 void GenerateMeshData( ImageId id,
292 const Vector2& position,
294 bool addReference = true );
297 * @brief Append second mesh to the first mesh
299 * @param[in] first First mesh
300 * @param[in] second Second mesh
301 * @param[in] optimize should we optimize vertex data
303 void StitchMesh( Mesh2D& first,
304 const Mesh2D& second,
305 bool optimize = false );
308 * @brief Combine two meshes, outputting the result into a new mesh
310 * @param[in] first First mesh
311 * @param[in] second Second mesh
312 * @param[in] optimize should we optimize vertex data
313 * @param[out] out resulting mesh
315 void StitchMesh( const Mesh2D& first,
316 const Mesh2D& second,
318 bool optimize = false );
321 * @brief Get the BufferImage containing an atlas
323 * @param[in] atlas AtlasId returned when atlas was created
325 * @return Atlas Handle
327 Dali::Atlas GetAtlasContainer( AtlasId atlas ) const;
330 * @brief Get the Id of the atlas containing an image
332 * @param[in] id ImageId
336 AtlasId GetAtlas( ImageId id );
338 * @brief Get the current size of an atlas
340 * @param[in] atlas AtlasId
342 * @return AtlasSize structure for the atlas
344 const AtlasSize& GetAtlasSize( AtlasId atlas );
347 * @brief Get the number of blocks available in an atlas
349 * @param[in] atlas AtlasId
351 * @return Number of blocks free in this atlas
353 SizeType GetFreeBlocks( AtlasId atlas );
356 * @brief Sets the pixel area of any new atlas and also the individual block size
358 * @param[in] size Atlas size structure
360 * @param blockSize pixel area in atlas for a block
362 void SetNewAtlasSize( const AtlasSize& size );
365 * @brief Get the number of atlases created
367 * @return number of atlases
369 SizeType GetAtlasCount() const;
372 * @brief Get the pixel format used by an atlas
374 * @param[in] atlas AtlasId
376 * @return Pixel format used by this atlas
378 Pixel::Format GetPixelFormat( AtlasId atlas );
381 * @brief Fill in a metrics structure showing current status of this Atlas Manager
383 * @param[in] metrics metrics structure to be filled
385 void GetMetrics( Metrics& metrics );
388 * @brief Get Material used by atlas
390 * @param atlas[in] atlas AtlasId
392 * @return Material used by atlas
394 Material GetMaterial( AtlasId atlas ) const;
397 * @brief Get Sampler used by atlas
399 * @param atlas[in] atlas AtlasId
401 * @return Sampler used by atlas
403 Sampler GetSampler( AtlasId atlas ) const;
406 explicit DALI_INTERNAL AtlasManager(Internal::AtlasManager *impl);
410 } // namespace Toolkit
414 #endif // __DALI_TOOLKIT_ATLAS_MANAGER_H__