SpriteSet.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. #ifndef GRAPHICS_SPRITESET_H // TODO for PR: Change the header guard when the name and location are finalised.
  2. #define GRAPHICS_SPRITESET_H
  3. #include <cstdlib>
  4. #include "../../../Include/RmlUi/Core/Types.h"
  5. namespace Rml {
  6. /**
  7. A texture atlas allocator that uses the shelf packing algorithm and supports fast addition and
  8. removal of images.
  9. @author Lê Duy Quang
  10. */
  11. // TODO for PR: Give a better name.
  12. class SpriteSet final {
  13. public:
  14. struct Handle {
  15. unsigned int slot_index;
  16. unsigned int epoch;
  17. };
  18. struct SpriteData {
  19. unsigned int texture_id;
  20. unsigned int x;
  21. unsigned int y;
  22. unsigned int width;
  23. unsigned int height;
  24. };
  25. /// Callback for when an image is migrated from one page to another.
  26. Function<void(unsigned int, Handle)> migration_callback;
  27. /// @param[in] bytes_per_pixel The number of bytes for each pixel (the pixel format is not needed for operation).
  28. /// @param[in] page_size The edge length in pixels of each texture page.
  29. /// @param[in] sprite_padding Number of blank pixels surrounding each image.
  30. SpriteSet(unsigned int bytes_per_pixel, unsigned int page_size, unsigned int sprite_padding);
  31. void Tick();
  32. /// Adds an image to the texture atlas.
  33. /// @param[in] width The width of the image.
  34. /// @param[in] height The height of the image.
  35. /// @param[in] data The image data.
  36. /// @return The handle to the image.
  37. Handle Add(const unsigned int width, const unsigned int height, const unsigned char* data) {
  38. return Add(width, height, data, width);
  39. }
  40. /// Adds a subimage to the texture atlas.
  41. /// @param[in] width The width of the subimage.
  42. /// @param[in] height The height of the subimage.
  43. /// @param[in] data Pointer to the first pixel of the subimage.
  44. /// @param[in] row_stride The width of the whole image that contains the subimage.
  45. /// @return The handle to the image.
  46. Handle Add(unsigned int width, unsigned int height, const unsigned char* data, unsigned int row_stride);
  47. /// Removes an image from the texture atlas.
  48. /// @param[in] handle The handle to the image.
  49. void Remove(Handle handle);
  50. /// Retrieves information about an image in the texture atlas.
  51. /// @param[in] handle The handle to the image.
  52. /// @return The information about the image.
  53. SpriteData Get(Handle handle) const;
  54. /// Retrieves texture data for all pages of the texture atlas.
  55. /// @return An array of pointers to each page's texture data.
  56. Vector<const unsigned char*> GetTextures() const;
  57. private:
  58. struct Page {
  59. unsigned int previous_index, next_index;
  60. unsigned int first_shelf_index;
  61. unsigned int texture_id;
  62. unsigned int first_dirty_y;
  63. unsigned int past_last_dirty_y;
  64. unsigned int first_dirty_x;
  65. unsigned int past_last_dirty_x;
  66. UniquePtr<std::vector<unsigned char>> texture_data;
  67. };
  68. struct Shelf {
  69. unsigned int page_index;
  70. unsigned int y;
  71. unsigned int height;
  72. unsigned int previous_index;
  73. unsigned int next_index;
  74. unsigned int first_slot_index;
  75. unsigned int first_free_slot_index;
  76. bool allocated;
  77. };
  78. struct Slot {
  79. unsigned int shelf_index;
  80. unsigned int texture_id;
  81. unsigned int x;
  82. unsigned int y;
  83. unsigned int width;
  84. unsigned int height;
  85. unsigned int actual_width;
  86. unsigned int previous_index;
  87. unsigned int next_index;
  88. unsigned int previous_free_index;
  89. unsigned int next_free_index;
  90. unsigned int epoch;
  91. bool allocated;
  92. };
  93. unsigned int bytes_per_pixel;
  94. unsigned int page_size;
  95. unsigned int sprite_padding;
  96. Vector<Page> page_pool{1 << 3};
  97. Vector<Shelf> shelf_pool{1 << 8};
  98. Vector<Slot> slot_pool{1 << 10};
  99. unsigned int page_count = 0;
  100. unsigned int first_page_index = static_cast<unsigned int>(-1);
  101. unsigned int last_page_index = 0;
  102. unsigned int next_free_shelf_index = 0;
  103. unsigned int next_free_slot_index = 0;
  104. unsigned int first_page_allocated_pixels = 0;
  105. unsigned int current_epoch = 0;
  106. unsigned int Allocate(unsigned int width, unsigned int height);
  107. unsigned int TryAllocateInPage(unsigned int page_index, unsigned int width, unsigned int height);
  108. unsigned int Remove(unsigned int slot_index);
  109. };
  110. } // namespace Rml
  111. #endif