diff options
author | Andreas Kling <kling@serenityos.org> | 2021-01-15 12:09:37 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-01-15 13:56:54 +0100 |
commit | 4d97b955e60ddc8cd763e703b91a0352407bf1ef (patch) | |
tree | c4dcbd8cf1f5db4068852c4e586565ea0be2e135 | |
parent | fb4993f0677a003c80a1c82f5aad3eccdd9a9beb (diff) | |
download | serenity-4d97b955e60ddc8cd763e703b91a0352407bf1ef.zip |
LibGfx: Allow creating a Gfx::Bitmap backed by an anonymous file
Gfx::Bitmap::create_with_anon_fd() creates such a Bitmap, and also
optionally takes ownership of the file, making sure to close() it
on destruction.
-rw-r--r-- | Userland/Libraries/LibGfx/Bitmap.cpp | 40 | ||||
-rw-r--r-- | Userland/Libraries/LibGfx/Bitmap.h | 10 |
2 files changed, 50 insertions, 0 deletions
diff --git a/Userland/Libraries/LibGfx/Bitmap.cpp b/Userland/Libraries/LibGfx/Bitmap.cpp index 7c031f59be..4df18ed136 100644 --- a/Userland/Libraries/LibGfx/Bitmap.cpp +++ b/Userland/Libraries/LibGfx/Bitmap.cpp @@ -182,6 +182,29 @@ static bool check_size(const IntSize& size, BitmapFormat format, unsigned actual return true; } +RefPtr<Bitmap> Bitmap::create_with_anon_fd(BitmapFormat format, int anon_fd, const IntSize& size, ShouldCloseAnonymousFile should_close_anon_fd) +{ + if (size_would_overflow(format, size)) + return nullptr; + + const auto pitch = minimum_pitch(size.width(), format); + const auto data_size_in_bytes = size_in_bytes(pitch, size.height()); + + auto* data = mmap(nullptr, round_up_to_power_of_two(data_size_in_bytes, PAGE_SIZE), PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, anon_fd, 0); + if (data == MAP_FAILED) { + perror("mmap"); + return nullptr; + } + + if (should_close_anon_fd == ShouldCloseAnonymousFile::Yes) { + int rc = close(anon_fd); + ASSERT(rc == 0); + anon_fd = -1; + } + + return adopt(*new Bitmap(format, anon_fd, size, data)); +} + RefPtr<Bitmap> Bitmap::create_with_shared_buffer(BitmapFormat format, NonnullRefPtr<SharedBuffer>&& shared_buffer, const IntSize& size, const Vector<RGBA32>& palette) { if (size_would_overflow(format, size)) @@ -293,6 +316,19 @@ Bitmap::Bitmap(BitmapFormat format, NonnullRefPtr<SharedBuffer>&& shared_buffer, allocate_palette_from_format(m_format, palette); } +Bitmap::Bitmap(BitmapFormat format, int anon_fd, const IntSize& size, void* data) + : m_size(size) + , m_data(data) + , m_pitch(minimum_pitch(size.width(), format)) + , m_format(format) + , m_needs_munmap(true) + , m_purgeable(true) + , m_anon_fd(anon_fd) +{ + ASSERT(!is_indexed()); + ASSERT(!size_would_overflow(format, size)); +} + RefPtr<Gfx::Bitmap> Bitmap::clone() const { RefPtr<Gfx::Bitmap> new_bitmap {}; @@ -378,6 +414,10 @@ Bitmap::~Bitmap() int rc = munmap(m_data, size_in_bytes()); ASSERT(rc == 0); } + if (m_anon_fd != -1) { + int rc = close(m_anon_fd); + ASSERT(rc == 0); + } m_data = nullptr; delete[] m_palette; } diff --git a/Userland/Libraries/LibGfx/Bitmap.h b/Userland/Libraries/LibGfx/Bitmap.h index 4d0b236f57..c816bed9a9 100644 --- a/Userland/Libraries/LibGfx/Bitmap.h +++ b/Userland/Libraries/LibGfx/Bitmap.h @@ -88,11 +88,17 @@ enum RotationDirection { class Bitmap : public RefCounted<Bitmap> { public: + enum class ShouldCloseAnonymousFile { + No, + Yes, + }; + static RefPtr<Bitmap> create(BitmapFormat, const IntSize&); static RefPtr<Bitmap> create_shareable(BitmapFormat, const IntSize&); static RefPtr<Bitmap> create_purgeable(BitmapFormat, const IntSize&); static RefPtr<Bitmap> create_wrapper(BitmapFormat, const IntSize&, size_t pitch, void*); static RefPtr<Bitmap> load_from_file(const StringView& path); + static RefPtr<Bitmap> create_with_anon_fd(BitmapFormat, int anon_fd, const IntSize&, ShouldCloseAnonymousFile); static RefPtr<Bitmap> create_with_shared_buffer(BitmapFormat, NonnullRefPtr<SharedBuffer>&&, const IntSize&); static RefPtr<Bitmap> create_with_shared_buffer(BitmapFormat, NonnullRefPtr<SharedBuffer>&&, const IntSize&, const Vector<RGBA32>& palette); static RefPtr<Bitmap> create_from_serialized_byte_buffer(ByteBuffer&& buffer); @@ -224,6 +230,8 @@ public: void set_volatile(); [[nodiscard]] bool set_nonvolatile(); + int anon_fd() const { return m_anon_fd; } + private: enum class Purgeable { No, @@ -232,6 +240,7 @@ private: Bitmap(BitmapFormat, const IntSize&, Purgeable, const BackingStore&); Bitmap(BitmapFormat, const IntSize&, size_t pitch, void*); Bitmap(BitmapFormat, NonnullRefPtr<SharedBuffer>&&, const IntSize&, const Vector<RGBA32>& palette); + Bitmap(BitmapFormat, int anon_fd, const IntSize&, void*); static Optional<BackingStore> allocate_backing_store(BitmapFormat, const IntSize&, Purgeable); @@ -246,6 +255,7 @@ private: bool m_purgeable { false }; bool m_volatile { false }; RefPtr<SharedBuffer> m_shared_buffer; + int m_anon_fd { -1 }; }; inline u8* Bitmap::scanline_u8(int y) |