Fix Klocwork issues.
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / atlas-manager / atlas-manager.h
1 #ifndef __DALI_TOOLKIT_ATLAS_MANAGER_H__
2 #define __DALI_TOOLKIT_ATLAS_MANAGER_H__
3
4 /*
5  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
6  *
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
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  */
19
20 // EXTERNAL INCLUDES
21 #include <stdint.h>
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>
26
27 namespace Dali
28 {
29
30 namespace Toolkit
31 {
32
33 namespace Internal DALI_INTERNAL
34 {
35
36 class AtlasManager;
37
38 } // namespace Internal
39
40 /**
41  * AtlasManager
42  * ------------
43  *
44  * Creates and manages additions and removals of images from Texture Atlases
45  *
46  * The AtlasManager will match pixeltype and optimal block use to determine
47  * the appropriate atlas to upload an image to.
48  *
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.
52  *
53  * Images are referenced by an ImageId once they have been successfully uploaded.
54  *
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.
58  *
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.
62  *
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.
66  *
67  * Examples using the AtlasManager
68  *
69  * Create or obtain the AtlasManager
70  * @code
71  *
72  * AtlasManager manager = AtlasManager::Get();
73  *
74  * @endcode
75  *
76  * Set the AtlasManager AddPolicy
77  *
78  * @code
79  *
80  * // Tell the atlas manager to create a new atlas, if it needs to
81  * manager.SetAddPolicy( FAIL_ON_ADD_CREATES );
82  *
83  * // Tell the atlas manager to return an error, if it can't add an image
84  * manager.SetAddPolicy( FAIL_ON_ADD_FAILS );
85  *
86  * @endcode
87  *
88  * Simple add and removal of BufferImage to and from an atlas
89  *
90  * @code
91  *
92  * // Structure returned by AtlasManager operations
93  * AtlasSlot slot;
94  *
95  * // Add image to an atlas ( will be created if none suitable exists )
96  * manager.Add( bitmapImage, slot );
97  *
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;
101  * if ( !imageId )
102  * {
103  *  // Addition has failed.....
104  * }
105  * ...
106  * ...
107  * // Done with image, so remove from atlas, if not being used elsewhere
108  * manager.Remove( imageId );
109  *
110  * @endcode
111  *
112  * Create a Specific Atlas for adding BufferImages to
113  *
114  * @code
115  *
116  * // Create an RGB888 atlas of 2048x2848, with a blocksize of 128x128
117  * uint32_t atlas = manager.CreateAtlas( 2048u, 2048u, 128u, 128u, Pixel::RGB888 );
118  *
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 );
122  *
123  * @endcode
124  *
125  * Create Geometry for a previously added image
126  *
127  * @code
128  *
129  * // Top left corner of geometry to be generated
130  * Vector2 position( 1.0f, 1.0f );
131  *
132  * // Geometry will end up here!
133  * MeshData meshData;
134  * manager.GenerateMeshData( imageId, position, meshData );
135  *
136  * @endcode
137  *
138  * Generating Geometry from multiple images in the same atlas
139  *
140  * @code
141  *
142  * MeshData firstMesh;
143  * MeshData secondMesh;
144  * manager.GenerateMeshData( imageid_1, position_1, firstMesh );
145  * manager.GenerateMeshData( imageid_2, position_2, secondMesh );
146  *
147  * // Combine the two meshes. Passing MESH_OPTIMIZE as an optional third parameter will remove duplicate vertices
148  * manager.StitchMesh( first, second );
149  *
150  * @endcode
151  *
152  */
153
154 class AtlasManager : public BaseHandle
155 {
156 public:
157
158   typedef uint32_t SizeType;
159   typedef SizeType AtlasId;
160   typedef SizeType ImageId;
161   static const bool MESH_OPTIMIZE = true;
162
163   struct AtlasSize
164   {
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
169   };
170
171   /**
172    * Metrics structures to describe Atlas Manager state
173    *
174    */
175   struct AtlasMetricsEntry
176   {
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
181   };
182
183   struct Metrics
184   {
185     Metrics()
186     : mAtlasCount( 0u ),
187       mTextureMemoryUsed( 0u )
188     {}
189
190     ~Metrics()
191     {}
192
193     SizeType mAtlasCount;                               ///< number of atlases
194     SizeType mTextureMemoryUsed;                        ///< texture memory used by atlases
195     Dali::Vector< AtlasMetricsEntry > mAtlasMetrics;    ///< container of atlas information
196   };
197
198   struct Vertex2D
199   {
200     Vector2 mPosition;
201     Vector2 mTexCoords;
202   };
203
204   struct Mesh2D
205   {
206     Vector< Vertex2D > mVertices;
207     Vector< unsigned int> mIndices;
208   };
209
210   /**
211    * Create an AtlasManager handle; this can be initialised with AtlasManager::New()
212    * Calling member functions with an uninitialised handle is not allowed.
213    */
214   AtlasManager();
215
216   /**
217    * @brief Get new instance of AtlasManager object.
218    *
219    * @return A handle to the AtlasManager control.
220    */
221   static AtlasManager New();
222
223   /**
224    * @brief Destructor
225    *
226    * This is non-virtual since derived Handle types must not contain data or virtual methods.
227    */
228   ~AtlasManager();
229
230   /**
231    * Policy on failing to add an image
232    */
233   enum AddFailPolicy
234   {
235     FAIL_ON_ADD_FAILS,
236     FAIL_ON_ADD_CREATES
237   };
238
239   /**
240    * @brief Container to hold result of placing texture into atlas
241    */
242   struct AtlasSlot
243   {
244     ImageId mImageId;                           ///< Id of stored Image
245     AtlasId mAtlasId;                           ///< Id of Atlas containing this slot
246   };
247
248   typedef Dali::Vector< AtlasManager::AtlasSlot > slotContainer;
249
250   /**
251    * @brief Create a blank atlas of specific dimensions and pixel format with a certain block size
252    *
253    * @param[in] size desired atlas dimensions
254    * @param[in] pixelformat format of a pixel in atlas
255    *
256    * @return atlas Id
257    */
258   AtlasId CreateAtlas( const AtlasSize& size, Pixel::Format pixelformat = Pixel::RGBA8888 );
259
260   /**
261    * @brief Set the policy on failure to add an image to an atlas
262    *
263    * @param policy policy to carry out if add fails
264    */
265   void SetAddPolicy( AddFailPolicy policy );
266
267   /**
268    * @brief Attempts to add an image to the most suitable atlas
269    *
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
273    *
274    * @param[in] image reference to a bitmapimage
275    * @param[out] slot result of add operation
276    * @param[in] atlas optional preferred atlas
277    */
278   void Add( const BufferImage& image,
279             AtlasSlot& slot,
280             AtlasId atlas = 0 );
281
282   /**
283    * @brief Remove previously added bitmapimage from atlas
284    *
285    * @param[in] id ImageId returned in the AtlasSlot from the add operation
286    *
287    * @return if true then image has been removed from the atlas
288    */
289   bool Remove( ImageId id );
290
291   /**
292    * @brief Generate mesh data for a previously added image
293    *
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
298    */
299   void GenerateMeshData( ImageId id,
300                          const Vector2& position,
301                          Mesh2D& mesh,
302                          bool addReference = true );
303
304   /**
305    * @brief Append second mesh to the first mesh
306    *
307    * @param[in] first First mesh
308    * @param[in] second Second mesh
309    * @param[in] optimize should we optimize vertex data
310    */
311   void StitchMesh( Mesh2D& first,
312                    const Mesh2D& second,
313                    bool optimize = false );
314
315   /**
316    * @brief Combine two meshes, outputting the result into a new mesh
317    *
318    * @param[in] first First mesh
319    * @param[in] second Second mesh
320    * @param[in] optimize should we optimize vertex data
321    * @param[out] out resulting mesh
322    */
323   void StitchMesh( const Mesh2D& first,
324                    const Mesh2D& second,
325                    Mesh2D& out,
326                    bool optimize = false );
327
328   /**
329    * @brief Get the BufferImage containing an atlas
330    *
331    * @param[in] atlas AtlasId returned when atlas was created
332    *
333    * @return Atlas Handle
334    */
335   Dali::Atlas GetAtlasContainer( AtlasId atlas ) const;
336
337   /**
338    * @brief Get the Id of the atlas containing an image
339    *
340    * @param[in] id ImageId
341    *
342    * @return Atlas Id
343    */
344   AtlasId GetAtlas( ImageId id );
345   /**
346    * @brief Get the current size of an atlas
347    *
348    * @param[in] atlas AtlasId
349    *
350    * @return AtlasSize structure for the atlas
351    */
352   const AtlasSize& GetAtlasSize( AtlasId atlas );
353
354   /**
355    * @brief Get the number of blocks available in an atlas
356    *
357    * @param[in] atlas AtlasId
358    *
359    * @return Number of blocks free in this atlas
360    */
361   SizeType GetFreeBlocks( AtlasId atlas );
362
363   /**
364    * @brief Sets the pixel area of any new atlas and also the individual block size
365    *
366    * @param[in] size Atlas size structure
367    *
368    * @param blockSize pixel area in atlas for a block
369    */
370   void SetNewAtlasSize( const AtlasSize& size );
371
372   /**
373    * @brief Get the number of atlases created
374    *
375    * @return number of atlases
376    */
377   SizeType GetAtlasCount() const;
378
379   /**
380    * @brief Get the pixel format used by an atlas
381    *
382    * @param[in] atlas AtlasId
383    *
384    * @return Pixel format used by this atlas
385    */
386   Pixel::Format GetPixelFormat( AtlasId atlas );
387
388   /**
389    * @brief Fill in a metrics structure showing current status of this Atlas Manager
390    *
391    * @param[in] metrics metrics structure to be filled
392    */
393   void GetMetrics( Metrics& metrics );
394
395   /**
396    * @brief Get Material used by atlas
397    *
398    * @param atlas[in] atlas AtlasId
399    *
400    * @return Material used by atlas
401    */
402   Material GetMaterial( AtlasId atlas ) const;
403
404  /**
405    * @brief Get Sampler used by atlas
406    *
407    * @param atlas[in] atlas AtlasId
408    *
409    * @return Sampler used by atlas
410    */
411   Sampler GetSampler( AtlasId atlas ) const;
412 private:
413
414   explicit DALI_INTERNAL AtlasManager(Internal::AtlasManager *impl);
415
416 };
417
418 } // namespace Toolkit
419
420 } // namespace Dali
421
422 #endif // __DALI_TOOLKIT_ATLAS_MANAGER_H__