diff --git a/Libraries/LibDraw/GraphicsBitmap.cpp b/Libraries/LibDraw/GraphicsBitmap.cpp index 736f9702d6..39e3708b91 100644 --- a/Libraries/LibDraw/GraphicsBitmap.cpp +++ b/Libraries/LibDraw/GraphicsBitmap.cpp @@ -9,17 +9,24 @@ NonnullRefPtr GraphicsBitmap::create(Format format, const Size& size) { - return adopt(*new GraphicsBitmap(format, size)); + return adopt(*new GraphicsBitmap(format, size, Purgeable::No)); } -GraphicsBitmap::GraphicsBitmap(Format format, const Size& size) +NonnullRefPtr GraphicsBitmap::create_purgeable(Format format, const Size& size) +{ + return adopt(*new GraphicsBitmap(format, size, Purgeable::Yes)); +} + +GraphicsBitmap::GraphicsBitmap(Format format, const Size& size, Purgeable purgeable) : m_size(size) , m_pitch(round_up_to_power_of_two(size.width() * sizeof(RGBA32), 16)) , m_format(format) + , m_purgeable(purgeable == Purgeable::Yes) { if (format == Format::Indexed8) m_palette = new RGBA32[256]; - m_data = (RGBA32*)mmap_with_name(nullptr, size_in_bytes(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0, String::format("GraphicsBitmap [%dx%d]", width(), height()).characters()); + int map_flags = purgeable == Purgeable::Yes ? (MAP_PURGEABLE | MAP_PRIVATE) : (MAP_ANONYMOUS | MAP_PRIVATE); + 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()); ASSERT(m_data && m_data != (void*)-1); m_needs_munmap = true; } @@ -111,3 +118,30 @@ void GraphicsBitmap::fill(Color color) fast_u32_fill(scanline, color.value(), width()); } } + +void GraphicsBitmap::set_volatile() +{ + ASSERT(m_purgeable); + if (m_volatile) + return; + int rc = madvise(m_data, size_in_bytes(), MADV_SET_VOLATILE); + if (rc < 0) { + perror("madvise(MADV_SET_VOLATILE)"); + ASSERT_NOT_REACHED(); + } + m_volatile = true; +} + +[[nodiscard]] bool GraphicsBitmap::set_nonvolatile() +{ + ASSERT(m_purgeable); + if (!m_volatile) + return true; + int rc = madvise(m_data, size_in_bytes(), MADV_SET_NONVOLATILE); + if (rc < 0) { + perror("madvise(MADV_SET_NONVOLATILE)"); + ASSERT_NOT_REACHED(); + } + m_volatile = false; + return rc == 0; +} diff --git a/Libraries/LibDraw/GraphicsBitmap.h b/Libraries/LibDraw/GraphicsBitmap.h index 47371ca02f..42695ed887 100644 --- a/Libraries/LibDraw/GraphicsBitmap.h +++ b/Libraries/LibDraw/GraphicsBitmap.h @@ -20,6 +20,7 @@ public: }; static NonnullRefPtr create(Format, const Size&); + static NonnullRefPtr create_purgeable(Format, const Size&); static NonnullRefPtr create_wrapper(Format, const Size&, size_t pitch, RGBA32*); static RefPtr load_from_file(const StringView& path); static RefPtr load_from_file(Format, const StringView& path, const Size&); @@ -98,8 +99,14 @@ public: set_pixel(position.x(), position.y(), color); } + bool is_purgeable() const { return m_purgeable; } + bool is_volatile() const { return m_volatile; } + void set_volatile(); + [[nodiscard]] bool set_nonvolatile(); + private: - GraphicsBitmap(Format, const Size&); + enum class Purgeable { No, Yes }; + GraphicsBitmap(Format, const Size&, Purgeable); GraphicsBitmap(Format, const Size&, size_t pitch, RGBA32*); GraphicsBitmap(Format, const Size&, MappedFile&&); GraphicsBitmap(Format, NonnullRefPtr&&, const Size&); @@ -110,6 +117,8 @@ private: size_t m_pitch { 0 }; Format m_format { Format::Invalid }; bool m_needs_munmap { false }; + bool m_purgeable { false }; + bool m_volatile { false }; MappedFile m_mapped_file; RefPtr m_shared_buffer; };