فهرست منبع

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.
Andreas Kling 4 سال پیش
والد
کامیت
4d97b955e6
2فایلهای تغییر یافته به همراه50 افزوده شده و 0 حذف شده
  1. 40 0
      Userland/Libraries/LibGfx/Bitmap.cpp
  2. 10 0
      Userland/Libraries/LibGfx/Bitmap.h

+ 40 - 0
Userland/Libraries/LibGfx/Bitmap.cpp

@@ -182,6 +182,29 @@ static bool check_size(const IntSize& size, BitmapFormat format, unsigned actual
     return true;
     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)
 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))
     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);
         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> Bitmap::clone() const
 {
 {
     RefPtr<Gfx::Bitmap> new_bitmap {};
     RefPtr<Gfx::Bitmap> new_bitmap {};
@@ -378,6 +414,10 @@ Bitmap::~Bitmap()
         int rc = munmap(m_data, size_in_bytes());
         int rc = munmap(m_data, size_in_bytes());
         ASSERT(rc == 0);
         ASSERT(rc == 0);
     }
     }
+    if (m_anon_fd != -1) {
+        int rc = close(m_anon_fd);
+        ASSERT(rc == 0);
+    }
     m_data = nullptr;
     m_data = nullptr;
     delete[] m_palette;
     delete[] m_palette;
 }
 }

+ 10 - 0
Userland/Libraries/LibGfx/Bitmap.h

@@ -88,11 +88,17 @@ enum RotationDirection {
 
 
 class Bitmap : public RefCounted<Bitmap> {
 class Bitmap : public RefCounted<Bitmap> {
 public:
 public:
+    enum class ShouldCloseAnonymousFile {
+        No,
+        Yes,
+    };
+
     static RefPtr<Bitmap> create(BitmapFormat, const IntSize&);
     static RefPtr<Bitmap> create(BitmapFormat, const IntSize&);
     static RefPtr<Bitmap> create_shareable(BitmapFormat, const IntSize&);
     static RefPtr<Bitmap> create_shareable(BitmapFormat, const IntSize&);
     static RefPtr<Bitmap> create_purgeable(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> create_wrapper(BitmapFormat, const IntSize&, size_t pitch, void*);
     static RefPtr<Bitmap> load_from_file(const StringView& path);
     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&);
     static RefPtr<Bitmap> create_with_shared_buffer(BitmapFormat, NonnullRefPtr<SharedBuffer>&&, const IntSize&, const Vector<RGBA32>& palette);
     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);
     static RefPtr<Bitmap> create_from_serialized_byte_buffer(ByteBuffer&& buffer);
@@ -224,6 +230,8 @@ public:
     void set_volatile();
     void set_volatile();
     [[nodiscard]] bool set_nonvolatile();
     [[nodiscard]] bool set_nonvolatile();
 
 
+    int anon_fd() const { return m_anon_fd; }
+
 private:
 private:
     enum class Purgeable {
     enum class Purgeable {
         No,
         No,
@@ -232,6 +240,7 @@ private:
     Bitmap(BitmapFormat, const IntSize&, Purgeable, const BackingStore&);
     Bitmap(BitmapFormat, const IntSize&, Purgeable, const BackingStore&);
     Bitmap(BitmapFormat, const IntSize&, size_t pitch, void*);
     Bitmap(BitmapFormat, const IntSize&, size_t pitch, void*);
     Bitmap(BitmapFormat, NonnullRefPtr<SharedBuffer>&&, const IntSize&, const Vector<RGBA32>& palette);
     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);
     static Optional<BackingStore> allocate_backing_store(BitmapFormat, const IntSize&, Purgeable);
 
 
@@ -246,6 +255,7 @@ private:
     bool m_purgeable { false };
     bool m_purgeable { false };
     bool m_volatile { false };
     bool m_volatile { false };
     RefPtr<SharedBuffer> m_shared_buffer;
     RefPtr<SharedBuffer> m_shared_buffer;
+    int m_anon_fd { -1 };
 };
 };
 
 
 inline u8* Bitmap::scanline_u8(int y)
 inline u8* Bitmap::scanline_u8(int y)