SpriteSet.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  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 "../../../Include/RmlUi/Core/Types.h"
  4. #include <cstdlib>
  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) { return Add(width, height, data, width); }
  38. /// Adds a subimage to the texture atlas.
  39. /// @param[in] width The width of the subimage.
  40. /// @param[in] height The height of the subimage.
  41. /// @param[in] data Pointer to the first pixel of the subimage.
  42. /// @param[in] row_stride The width of the whole image that contains the subimage.
  43. /// @return The handle to the image.
  44. Handle Add(unsigned int width, unsigned int height, const unsigned char* data, unsigned int row_stride);
  45. /// Removes an image from the texture atlas.
  46. /// @param[in] handle The handle to the image.
  47. void Remove(Handle handle);
  48. /// Retrieves information about an image in the texture atlas.
  49. /// @param[in] handle The handle to the image.
  50. /// @return The information about the image.
  51. SpriteData Get(Handle handle) const;
  52. /// Retrieves texture data for all pages of the texture atlas.
  53. /// @return An array of pointers to each page's texture data.
  54. Vector<const unsigned char*> GetTextures() const;
  55. private:
  56. struct Page {
  57. unsigned int previous_index, next_index;
  58. unsigned int first_shelf_index;
  59. unsigned int texture_id;
  60. unsigned int first_dirty_y;
  61. unsigned int past_last_dirty_y;
  62. unsigned int first_dirty_x;
  63. unsigned int past_last_dirty_x;
  64. UniquePtr<unsigned char[]> texture_data;
  65. };
  66. struct Shelf {
  67. unsigned int page_index;
  68. unsigned int y;
  69. unsigned int height;
  70. unsigned int previous_index;
  71. unsigned int next_index;
  72. unsigned int first_slot_index;
  73. unsigned int first_free_slot_index;
  74. bool allocated;
  75. };
  76. struct Slot {
  77. unsigned int shelf_index;
  78. unsigned int texture_id;
  79. unsigned int x;
  80. unsigned int y;
  81. unsigned int width;
  82. unsigned int height;
  83. unsigned int actual_width;
  84. unsigned int previous_index;
  85. unsigned int next_index;
  86. unsigned int previous_free_index;
  87. unsigned int next_free_index;
  88. unsigned int epoch;
  89. bool allocated;
  90. };
  91. unsigned int bytes_per_pixel;
  92. unsigned int page_size;
  93. unsigned int sprite_padding;
  94. Vector<Page> page_pool{1 << 3};
  95. Vector<Shelf> shelf_pool{1 << 8};
  96. Vector<Slot> slot_pool{1 << 10};
  97. unsigned int page_count = 0;
  98. unsigned int first_page_index = static_cast<unsigned int>(-1);
  99. unsigned int last_page_index = 0;
  100. unsigned int next_free_shelf_index = 0;
  101. unsigned int next_free_slot_index = 0;
  102. unsigned int first_page_allocated_pixels = 0;
  103. unsigned int current_epoch = 0;
  104. unsigned int Allocate(unsigned int width, unsigned int height);
  105. unsigned int TryAllocateInPage(unsigned int page_index, unsigned int width, unsigned int height);
  106. unsigned int Remove(unsigned int slot_index);
  107. };
  108. } // namespace Rml
  109. #endif