GraphicsBitmap.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #include <AK/MappedFile.h>
  2. #include <LibDraw/GraphicsBitmap.h>
  3. #include <LibDraw/PNGLoader.h>
  4. #include <errno.h>
  5. #include <fcntl.h>
  6. #include <stdio.h>
  7. #include <sys/mman.h>
  8. #include <unistd.h>
  9. NonnullRefPtr<GraphicsBitmap> GraphicsBitmap::create(Format format, const Size& size)
  10. {
  11. return adopt(*new GraphicsBitmap(format, size, Purgeable::No));
  12. }
  13. NonnullRefPtr<GraphicsBitmap> GraphicsBitmap::create_purgeable(Format format, const Size& size)
  14. {
  15. return adopt(*new GraphicsBitmap(format, size, Purgeable::Yes));
  16. }
  17. GraphicsBitmap::GraphicsBitmap(Format format, const Size& size, Purgeable purgeable)
  18. : m_size(size)
  19. , m_pitch(round_up_to_power_of_two(size.width() * sizeof(RGBA32), 16))
  20. , m_format(format)
  21. , m_purgeable(purgeable == Purgeable::Yes)
  22. {
  23. if (format == Format::Indexed8)
  24. m_palette = new RGBA32[256];
  25. int map_flags = purgeable == Purgeable::Yes ? (MAP_PURGEABLE | MAP_PRIVATE) : (MAP_ANONYMOUS | MAP_PRIVATE);
  26. m_data = (RGBA32*)mmap_with_name(nullptr, size_in_bytes(), PROT_READ | PROT_WRITE, map_flags, 0, 0, String::format("GraphicsBitmap [%dx%d]", width(), height()).characters());
  27. ASSERT(m_data && m_data != (void*)-1);
  28. m_needs_munmap = true;
  29. }
  30. NonnullRefPtr<GraphicsBitmap> GraphicsBitmap::create_wrapper(Format format, const Size& size, size_t pitch, RGBA32* data)
  31. {
  32. return adopt(*new GraphicsBitmap(format, size, pitch, data));
  33. }
  34. RefPtr<GraphicsBitmap> GraphicsBitmap::load_from_file(const StringView& path)
  35. {
  36. return load_png(path);
  37. }
  38. RefPtr<GraphicsBitmap> GraphicsBitmap::load_from_file(Format format, const StringView& path, const Size& size)
  39. {
  40. MappedFile mapped_file(path);
  41. if (!mapped_file.is_valid())
  42. return nullptr;
  43. return adopt(*new GraphicsBitmap(format, size, move(mapped_file)));
  44. }
  45. GraphicsBitmap::GraphicsBitmap(Format format, const Size& size, size_t pitch, RGBA32* data)
  46. : m_size(size)
  47. , m_data(data)
  48. , m_pitch(pitch)
  49. , m_format(format)
  50. {
  51. if (format == Format::Indexed8)
  52. m_palette = new RGBA32[256];
  53. }
  54. GraphicsBitmap::GraphicsBitmap(Format format, const Size& size, MappedFile&& mapped_file)
  55. : m_size(size)
  56. , m_data((RGBA32*)mapped_file.data())
  57. , m_pitch(round_up_to_power_of_two(size.width() * sizeof(RGBA32), 16))
  58. , m_format(format)
  59. , m_mapped_file(move(mapped_file))
  60. {
  61. ASSERT(format != Format::Indexed8);
  62. }
  63. NonnullRefPtr<GraphicsBitmap> GraphicsBitmap::create_with_shared_buffer(Format format, NonnullRefPtr<SharedBuffer>&& shared_buffer, const Size& size)
  64. {
  65. return adopt(*new GraphicsBitmap(format, move(shared_buffer), size));
  66. }
  67. GraphicsBitmap::GraphicsBitmap(Format format, NonnullRefPtr<SharedBuffer>&& shared_buffer, const Size& size)
  68. : m_size(size)
  69. , m_data((RGBA32*)shared_buffer->data())
  70. , m_pitch(round_up_to_power_of_two(size.width() * sizeof(RGBA32), 16))
  71. , m_format(format)
  72. , m_shared_buffer(move(shared_buffer))
  73. {
  74. ASSERT(format != Format::Indexed8);
  75. }
  76. NonnullRefPtr<GraphicsBitmap> GraphicsBitmap::to_shareable_bitmap() const
  77. {
  78. if (m_shared_buffer)
  79. return *this;
  80. auto buffer = SharedBuffer::create_with_size(size_in_bytes());
  81. auto bitmap = GraphicsBitmap::create_with_shared_buffer(m_format, *buffer, m_size);
  82. memcpy(buffer->data(), scanline(0), size_in_bytes());
  83. return bitmap;
  84. }
  85. GraphicsBitmap::~GraphicsBitmap()
  86. {
  87. if (m_needs_munmap) {
  88. int rc = munmap(m_data, size_in_bytes());
  89. ASSERT(rc == 0);
  90. }
  91. m_data = nullptr;
  92. delete[] m_palette;
  93. }
  94. void GraphicsBitmap::set_mmap_name(const StringView& name)
  95. {
  96. ASSERT(m_needs_munmap);
  97. ::set_mmap_name(m_data, size_in_bytes(), String(name).characters());
  98. }
  99. void GraphicsBitmap::fill(Color color)
  100. {
  101. ASSERT(m_format == GraphicsBitmap::Format::RGB32 || m_format == GraphicsBitmap::Format::RGBA32);
  102. for (int y = 0; y < height(); ++y) {
  103. auto* scanline = this->scanline(y);
  104. fast_u32_fill(scanline, color.value(), width());
  105. }
  106. }
  107. void GraphicsBitmap::set_volatile()
  108. {
  109. ASSERT(m_purgeable);
  110. if (m_volatile)
  111. return;
  112. int rc = madvise(m_data, size_in_bytes(), MADV_SET_VOLATILE);
  113. if (rc < 0) {
  114. perror("madvise(MADV_SET_VOLATILE)");
  115. ASSERT_NOT_REACHED();
  116. }
  117. m_volatile = true;
  118. }
  119. [[nodiscard]] bool GraphicsBitmap::set_nonvolatile()
  120. {
  121. ASSERT(m_purgeable);
  122. if (!m_volatile)
  123. return true;
  124. int rc = madvise(m_data, size_in_bytes(), MADV_SET_NONVOLATILE);
  125. if (rc < 0) {
  126. perror("madvise(MADV_SET_NONVOLATILE)");
  127. ASSERT_NOT_REACHED();
  128. }
  129. m_volatile = false;
  130. return rc == 0;
  131. }