Move new mesh API to devel-api.
[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     SizeType mAtlasCount;                               // number of atlases
186     SizeType mTextureMemoryUsed;                        // texture memory used by atlases
187     Dali::Vector< AtlasMetricsEntry > mAtlasMetrics;    // container of atlas information
188   };
189
190   struct Vertex2D
191   {
192     Vector2 mPosition;
193     Vector2 mTexCoords;
194   };
195
196   struct Mesh2D
197   {
198     Vector< Vertex2D > mVertices;
199     Vector< unsigned int> mIndices;
200   };
201
202   /**
203    * Create an AtlasManager handle; this can be initialised with AtlasManager::New()
204    * Calling member functions with an uninitialised handle is not allowed.
205    */
206   AtlasManager();
207
208   /**
209    * @brief Get new instance of AtlasManager object.
210    *
211    * @return A handle to the AtlasManager control.
212    */
213   static AtlasManager New();
214
215   /**
216    * @brief Destructor
217    *
218    * This is non-virtual since derived Handle types must not contain data or virtual methods.
219    */
220   ~AtlasManager();
221
222   /**
223    * Policy on failing to add an image
224    */
225   enum AddFailPolicy
226   {
227     FAIL_ON_ADD_FAILS,
228     FAIL_ON_ADD_CREATES
229   };
230
231   /**
232    * @brief Container to hold result of placing texture into atlas
233    */
234   struct AtlasSlot
235   {
236     ImageId mImageId;                           // Id of stored Image
237     AtlasId mAtlasId;                           // Id of Atlas containing this slot
238   };
239
240   typedef Dali::Vector< AtlasManager::AtlasSlot > slotContainer;
241
242   /**
243    * @brief Create a blank atlas of specific dimensions and pixel format with a certain block size
244    *
245    * @param[in] size desired atlas dimensions
246    * @param[in] pixelformat format of a pixel in atlas
247    *
248    * @return atlas Id
249    */
250   AtlasId CreateAtlas( const AtlasSize& size, Pixel::Format pixelformat = Pixel::RGBA8888 );
251
252   /**
253    * @brief Set the policy on failure to add an image to an atlas
254    *
255    * @param policy policy to carry out if add fails
256    */
257   void SetAddPolicy( AddFailPolicy policy );
258
259   /**
260    * @brief Attempts to add an image to the most suitable atlas
261    *
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
265    *
266    * @param[in] image reference to a bitmapimage
267    * @param[out] slot result of add operation
268    * @param[in] atlas optional preferred atlas
269    */
270   void Add( const BufferImage& image,
271             AtlasSlot& slot,
272             AtlasId atlas = 0 );
273
274   /**
275    * @brief Remove previously added bitmapimage from atlas
276    *
277    * @param[in] id ImageId returned in the AtlasSlot from the add operation
278    *
279    * @return if true then image has been removed from the atlas
280    */
281   bool Remove( ImageId id );
282
283   /**
284    * @brief Generate mesh data for a previously added image
285    *
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    */
290   void GenerateMeshData( ImageId id,
291                          const Vector2& position,
292                          Mesh2D& mesh );
293
294   /**
295    * @brief Append second mesh to the first mesh
296    *
297    * @param[in] first First mesh
298    * @param[in] second Second mesh
299    * @param[in] optimize should we optimize vertex data
300    */
301   void StitchMesh( Mesh2D& first,
302                    const Mesh2D& second,
303                    bool optimize = false );
304
305   /**
306    * @brief Combine two meshes, outputting the result into a new mesh
307    *
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
312    */
313   void StitchMesh( const Mesh2D& first,
314                    const Mesh2D& second,
315                    Mesh2D& out,
316                    bool optimize = false );
317
318   /**
319    * @brief Get the BufferImage containing an atlas
320    *
321    * @param[in] atlas AtlasId returned when atlas was created
322    *
323    * @return Atlas Handle
324    */
325   Dali::Atlas GetAtlasContainer( AtlasId atlas ) const;
326
327   /**
328    * @brief Get the Id of the atlas containing an image
329    *
330    * @param[in] id ImageId
331    *
332    * @return Atlas Id
333    */
334   AtlasId GetAtlas( ImageId id );
335   /**
336    * @brief Get the current size of an atlas
337    *
338    * @param[in] atlas AtlasId
339    *
340    * @return AtlasSize structure for the atlas
341    */
342   const AtlasSize& GetAtlasSize( AtlasId atlas );
343
344   /**
345    * @brief Get the number of blocks available in an atlas
346    *
347    * @param[in] atlas AtlasId
348    *
349    * @return Number of blocks free in this atlas
350    */
351   SizeType GetFreeBlocks( AtlasId atlas );
352
353   /**
354    * @brief Sets the pixel area of any new atlas and also the individual block size
355    *
356    * @param[in] size Atlas size structure
357    *
358    * @param blockSize pixel area in atlas for a block
359    */
360   void SetNewAtlasSize( const AtlasSize& size );
361
362   /**
363    * @brief Get the number of atlases created
364    *
365    * @return number of atlases
366    */
367   SizeType GetAtlasCount() const;
368
369   /**
370    * @brief Get the pixel format used by an atlas
371    *
372    * @param[in] atlas AtlasId
373    *
374    * @return Pixel format used by this atlas
375    */
376   Pixel::Format GetPixelFormat( AtlasId atlas );
377
378   /**
379    * @brief Fill in a metrics structure showing current status of this Atlas Manager
380    *
381    * @param[in] metrics metrics structure to be filled
382    */
383   void GetMetrics( Metrics& metrics );
384
385   /**
386    * @brief Get Material used by atlas
387    *
388    * @param atlas[in] atlas AtlasId
389    *
390    * @return Material used by atlas
391    */
392   Material GetMaterial( AtlasId atlas ) const;
393
394  /**
395    * @brief Get Sampler used by atlas
396    *
397    * @param atlas[in] atlas AtlasId
398    *
399    * @return Sampler used by atlas
400    */
401   Sampler GetSampler( AtlasId atlas ) const;
402 private:
403
404   explicit DALI_INTERNAL AtlasManager(Internal::AtlasManager *impl);
405
406 };
407
408 } // namespace Toolkit
409
410 } // namespace Dali
411
412 #endif // __DALI_TOOLKIT_ATLAS_MANAGER_H__