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/devel-api/images/atlas.h>
24 #include <dali/public-api/images/buffer-image.h>
25 #include <dali/public-api/shader-effects/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
290 void GenerateMeshData( ImageId id,
291 const Vector2& position,
295 * @brief Append second mesh to the first mesh
297 * @param[in] first First mesh
298 * @param[in] second Second mesh
299 * @param[in] optimize should we optimize vertex data
301 void StitchMesh( Mesh2D& first,
302 const Mesh2D& second,
303 bool optimize = false );
306 * @brief Combine two meshes, outputting the result into a new mesh
308 * @param[in] first First mesh
309 * @param[in] second Second mesh
310 * @param[in] optimize should we optimize vertex data
311 * @param[out] out resulting mesh
313 void StitchMesh( const Mesh2D& first,
314 const Mesh2D& second,
316 bool optimize = false );
319 * @brief Get the BufferImage containing an atlas
321 * @param[in] atlas AtlasId returned when atlas was created
323 * @return Atlas Handle
325 Dali::Atlas GetAtlasContainer( AtlasId atlas ) const;
328 * @brief Get the Id of the atlas containing an image
330 * @param[in] id ImageId
334 AtlasId GetAtlas( ImageId id );
336 * @brief Get the current size of an atlas
338 * @param[in] atlas AtlasId
340 * @return AtlasSize structure for the atlas
342 const AtlasSize& GetAtlasSize( AtlasId atlas );
345 * @brief Get the number of blocks available in an atlas
347 * @param[in] atlas AtlasId
349 * @return Number of blocks free in this atlas
351 SizeType GetFreeBlocks( AtlasId atlas );
354 * @brief Sets the pixel area of any new atlas and also the individual block size
356 * @param[in] size Atlas size structure
358 * @param blockSize pixel area in atlas for a block
360 void SetNewAtlasSize( const AtlasSize& size );
363 * @brief Get the number of atlases created
365 * @return number of atlases
367 SizeType GetAtlasCount() const;
370 * @brief Get the pixel format used by an atlas
372 * @param[in] atlas AtlasId
374 * @return Pixel format used by this atlas
376 Pixel::Format GetPixelFormat( AtlasId atlas );
379 * @brief Fill in a metrics structure showing current status of this Atlas Manager
381 * @param[in] metrics metrics structure to be filled
383 void GetMetrics( Metrics& metrics );
386 * @brief Get Material used by atlas
388 * @param atlas[in] atlas AtlasId
390 * @return Material used by atlas
392 Material GetMaterial( AtlasId atlas ) const;
395 * @brief Get Sampler used by atlas
397 * @param atlas[in] atlas AtlasId
399 * @return Sampler used by atlas
401 Sampler GetSampler( AtlasId atlas ) const;
404 explicit DALI_INTERNAL AtlasManager(Internal::AtlasManager *impl);
408 } // namespace Toolkit
412 #endif // __DALI_TOOLKIT_ATLAS_MANAGER_H__