tb_bitmap_fragment.h 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. // ================================================================================
  2. // == This file is a part of Turbo Badger. (C) 2011-2014, Emil Segerås ==
  3. // == See tb_core.h for more information. ==
  4. // ================================================================================
  5. #ifndef TB_BITMAP_FRAGMENT_H
  6. #define TB_BITMAP_FRAGMENT_H
  7. #include "tb_core.h"
  8. #include "tb_geometry.h"
  9. #include "tb_hashtable.h"
  10. #include "tb_list.h"
  11. #include "tb_id.h"
  12. #include "tb_linklist.h"
  13. namespace tb {
  14. class TBBitmapFragment;
  15. class TBBitmap;
  16. /** Return the nearest power of two from val.
  17. F.ex 110 -> 128, 256->256, 257->512 etc. */
  18. int TBGetNearestPowerOfTwo(int val);
  19. /** TBImageloader is a class used to load skin images. It can be implemented
  20. in any way the system wants, but the system has to provide a image loader
  21. capable of handling all image formats used in the skin. */
  22. class TBImageLoader
  23. {
  24. public:
  25. /** Static method used to create an image loader. The system must implement this
  26. function and create an implementation of the TBImageLoader interface. */
  27. static TBImageLoader *CreateFromFile(const char *filename);
  28. virtual ~TBImageLoader() {}
  29. /** Return the width of the loaded bitmap. */
  30. virtual int Width() = 0;
  31. /** Return the height of the loaded bitmap. */
  32. virtual int Height() = 0;
  33. /** Return the data of the loaded bitmap.
  34. This data should always be in 32bit RGBA format. */
  35. virtual uint32 *Data() = 0;
  36. };
  37. /** Allocator of space out of a given available space. */
  38. class TBSpaceAllocator
  39. {
  40. public:
  41. /** A chunk of space */
  42. class Space : public TBLinkOf<Space>
  43. {
  44. public:
  45. int x, width;
  46. };
  47. TBSpaceAllocator(int available_space)
  48. : m_available_space(available_space) { }
  49. /** Return true if no allocations are currently live using this allocator. */
  50. bool IsAllAvailable() const { return !m_used_space_list.HasLinks(); }
  51. /** Return true if the given width is currently available. */
  52. bool HasSpace(int needed_w) const;
  53. /** Allocate the given space and return the Space, or nullptr on error. */
  54. Space *AllocSpace(int needed_w);
  55. /** Free the given space so it is available for new allocations. */
  56. void FreeSpace(Space *space);
  57. private:
  58. Space *GetSmallestAvailableSpace(int needed_w);
  59. int m_available_space;
  60. TBLinkListAutoDeleteOf<Space> m_free_space_list;
  61. TBLinkListAutoDeleteOf<Space> m_used_space_list;
  62. };
  63. /** Allocates space for TBBitmapFragment in a row (used in TBBitmapFragmentMap). */
  64. class TBFragmentSpaceAllocator : public TBSpaceAllocator
  65. {
  66. public:
  67. TBFragmentSpaceAllocator(int y, int width, int height)
  68. : TBSpaceAllocator(width), y(y), height(height) {}
  69. int y, height;
  70. };
  71. /** Specify when the bitmap should be validated when calling TBBitmapFragmentMap::GetBitmap. */
  72. enum TB_VALIDATE_TYPE {
  73. /** Always validate the bitmap (The bitmap is updated if needed) */
  74. TB_VALIDATE_ALWAYS,
  75. /** Only validate if the bitmap does not yet exist (Make sure there is
  76. a valid bitmap pointer, but the data is not necessarily updated) */
  77. TB_VALIDATE_FIRST_TIME
  78. };
  79. /** TBBitmapFragmentMap is used to pack multiple bitmaps into a single TBBitmap.
  80. When initialized (in a size suitable for a TBBitmap) is also creates a software buffer
  81. that will make up the TBBitmap when all fragments have been added. */
  82. class TBBitmapFragmentMap
  83. {
  84. public:
  85. TBBitmapFragmentMap();
  86. ~TBBitmapFragmentMap();
  87. /** Initialize the map with the given size. The size should be a power of two since
  88. it will be used to create a TBBitmap (texture memory). */
  89. bool Init(int bitmap_w, int bitmap_h);
  90. /** Create a new fragment with the given size and data in this map.
  91. Returns nullptr if there is not enough room in this map or on any other fail. */
  92. TBBitmapFragment *CreateNewFragment(int frag_w, int frag_h, int data_stride, uint32 *frag_data, bool add_border);
  93. /** Free up the space used by the given fragment, so that other fragments can take its place. */
  94. void FreeFragmentSpace(TBBitmapFragment *frag);
  95. /** Return the bitmap for this map.
  96. By default, the bitmap is validated if needed before returning (See TB_VALIDATE_TYPE) */
  97. TBBitmap *GetBitmap(TB_VALIDATE_TYPE validate_type = TB_VALIDATE_ALWAYS);
  98. private:
  99. friend class TBBitmapFragmentManager;
  100. bool ValidateBitmap();
  101. void DeleteBitmap();
  102. void CopyData(TBBitmapFragment *frag, int data_stride, uint32 *frag_data, int border);
  103. TBListAutoDeleteOf<TBFragmentSpaceAllocator> m_rows;
  104. int m_bitmap_w, m_bitmap_h;
  105. uint32 *m_bitmap_data;
  106. TBBitmap *m_bitmap;
  107. bool m_need_update;
  108. int m_allocated_pixels;
  109. };
  110. /** TBBitmapFragment represents a sub part of a TBBitmap.
  111. It's owned by TBBitmapFragmentManager which pack multiple
  112. TBBitmapFragment within TBBitmaps to reduce texture switching. */
  113. class TBBitmapFragment
  114. {
  115. public:
  116. /** Return the width of the bitmap fragment. */
  117. int Width() const { return m_rect.w; }
  118. /** Return the height of the bitmap fragment. */
  119. int Height() const { return m_rect.h; }
  120. /** Return the bitmap for this fragment.
  121. By default, the bitmap is validated if needed before returning (See TB_VALIDATE_TYPE) */
  122. TBBitmap *GetBitmap(TB_VALIDATE_TYPE validate_type = TB_VALIDATE_ALWAYS) { return m_map->GetBitmap(validate_type); }
  123. /** Return the height allocated to this fragment. This may be larger than Height() depending
  124. of the internal allocation of fragments in a map. It should rarely be used. */
  125. int GetAllocatedHeight() const { return m_row_height; }
  126. public:
  127. TBBitmapFragmentMap *m_map;
  128. TBRect m_rect;
  129. TBFragmentSpaceAllocator *m_row;
  130. TBFragmentSpaceAllocator::Space *m_space;
  131. TBID m_id;
  132. int m_row_height;
  133. /** This uint32 is reserved for batching renderer backends. It's not used
  134. internally, but always initialized to 0xffffffff for all new fragments. */
  135. uint32 m_batch_id;
  136. };
  137. /** TBBitmapFragmentManager manages loading bitmaps of arbitrary size,
  138. pack as many of them into as few TBBitmap as possible.
  139. It also makes sure that only one instance of each file is loaded,
  140. so f.ex loading "foo.png" many times still load and allocate one
  141. TBBitmapFragment. */
  142. class TBBitmapFragmentManager
  143. {
  144. public:
  145. TBBitmapFragmentManager();
  146. ~TBBitmapFragmentManager();
  147. /** Set to true if a 1px border should be added to new fragments so stretched
  148. drawing won't get filtering artifacts at the edges (default is disabled). */
  149. void SetAddBorder(bool add_border) { m_add_border = add_border; }
  150. bool GetAddBorder() const { return m_add_border; }
  151. /** Get the fragment with the given image filename. If it's not already loaded,
  152. it will be loaded into a new fragment with the filename as id.
  153. returns nullptr on fail. */
  154. TBBitmapFragment *GetFragmentFromFile(const char *filename, bool dedicated_map);
  155. /** Get the fragment with the given id, or nullptr if it doesn't exist. */
  156. TBBitmapFragment *GetFragment(const TBID &id) const;
  157. /** Create a new fragment from the given data.
  158. @param id The id that should be used to identify the fragment.
  159. @param dedicated_map if true, it will get a dedicated map.
  160. @param data_w the width of the data.
  161. @param data_h the height of the data.
  162. @param data_stride the number of pixels in a row of the input data.
  163. @param data pointer to the data in BGRA32 format. */
  164. TBBitmapFragment *CreateNewFragment(const TBID &id, bool dedicated_map,
  165. int data_w, int data_h, int data_stride,
  166. uint32 *data);
  167. /** Delete the given fragment and free the space it used in its map,
  168. so that other fragments can take its place. */
  169. void FreeFragment(TBBitmapFragment *frag);
  170. /** Clear all loaded bitmaps and all created bitmap fragments and maps.
  171. After this call, do not keep any pointers to any TBBitmapFragment created
  172. by this fragment manager. */
  173. void Clear();
  174. /** Validate bitmaps on fragment maps that has changed. */
  175. bool ValidateBitmaps();
  176. /** Delete all bitmaps in all fragment maps in this manager.
  177. The bitmaps will be recreated automatically when needed, or when
  178. calling ValidateBitmaps. You do not need to call this, except when
  179. the context is lost and all bitmaps must be forgotten. */
  180. void DeleteBitmaps();
  181. /** Get number of fragment maps that is currently used. */
  182. int GetNumMaps() const { return m_fragment_maps.GetNumItems(); }
  183. /** Set the number of maps (TBBitmaps) this manager should be allowed to create.
  184. If a new fragment can't fit into any existing bitmap and the limit is reached,
  185. the fragment creation will fail. Set to 0 for unlimited (default). */
  186. void SetNumMapsLimit(int num_maps_limit);
  187. /** Set the default size of new fragment maps. These must be power of two. */
  188. void SetDefaultMapSize(int w, int h);
  189. /** Get the amount (in percent) of space that is currently occupied by all maps
  190. in this fragment manager. */
  191. int GetUseRatio() const;
  192. #ifdef TB_RUNTIME_DEBUG_INFO
  193. /** Render the maps on screen, to analyze fragment positioning. */
  194. void Debug();
  195. #endif
  196. private:
  197. TBListOf<TBBitmapFragmentMap> m_fragment_maps;
  198. TBHashTableOf<TBBitmapFragment> m_fragments;
  199. int m_num_maps_limit;
  200. bool m_add_border;
  201. int m_default_map_w;
  202. int m_default_map_h;
  203. };
  204. }; // namespace tb
  205. #endif // TB_BITMAP_FRAGMENT_H