summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-01-15 12:09:37 +0100
committerAndreas Kling <kling@serenityos.org>2021-01-15 13:56:54 +0100
commit4d97b955e60ddc8cd763e703b91a0352407bf1ef (patch)
treec4dcbd8cf1f5db4068852c4e586565ea0be2e135
parentfb4993f0677a003c80a1c82f5aad3eccdd9a9beb (diff)
downloadserenity-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.cpp40
-rw-r--r--Userland/Libraries/LibGfx/Bitmap.h10
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)