瀏覽代碼

LibGfx: Use anonymous buffer instead of raw anon_fd for Gfx::Bitmap

Instead of using a low-level, proprietary API inside LibGfx, let's use
Core::AnonymousBuffer which already abstracts anon_fd and offers a
higher-level API too.
Jean-Baptiste Boric 4 年之前
父節點
當前提交
e4394b1605

+ 4 - 5
Userland/Libraries/LibGUI/Window.cpp

@@ -23,7 +23,6 @@
 #include <LibGUI/WindowServerConnection.h>
 #include <LibGfx/Bitmap.h>
 #include <fcntl.h>
-#include <serenity.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -744,7 +743,7 @@ void Window::set_hovered_widget(Widget* widget)
 void Window::set_current_backing_store(WindowBackingStore& backing_store, bool flush_immediately)
 {
     auto& bitmap = backing_store.bitmap();
-    WindowServerConnection::the().set_window_backing_store(m_window_id, 32, bitmap.pitch(), bitmap.anon_fd(), backing_store.serial(), bitmap.has_alpha_channel(), bitmap.size(), flush_immediately);
+    WindowServerConnection::the().set_window_backing_store(m_window_id, 32, bitmap.pitch(), bitmap.anonymous_buffer().fd(), backing_store.serial(), bitmap.has_alpha_channel(), bitmap.size(), flush_immediately);
 }
 
 void Window::flip(const Vector<Gfx::IntRect, 32>& dirty_rects)
@@ -777,14 +776,14 @@ OwnPtr<WindowBackingStore> Window::create_backing_store(const Gfx::IntSize& size
     size_t pitch = Gfx::Bitmap::minimum_pitch(size.width(), format);
     size_t size_in_bytes = size.height() * pitch;
 
-    auto anon_fd = anon_create(round_up_to_power_of_two(size_in_bytes, PAGE_SIZE), O_CLOEXEC);
-    if (anon_fd < 0) {
+    auto buffer = Core::AnonymousBuffer::create_with_size(round_up_to_power_of_two(size_in_bytes, PAGE_SIZE));
+    if (!buffer.is_valid()) {
         perror("anon_create");
         return {};
     }
 
     // FIXME: Plumb scale factor here eventually.
-    auto bitmap = Gfx::Bitmap::create_with_anon_fd(format, anon_fd, size, 1, {}, Gfx::Bitmap::ShouldCloseAnonymousFile::No);
+    auto bitmap = Gfx::Bitmap::create_with_anonymous_buffer(format, buffer, size, 1, {});
     if (!bitmap)
         return {};
     return make<WindowBackingStore>(bitmap.release_nonnull());

+ 16 - 52
Userland/Libraries/LibGfx/Bitmap.cpp

@@ -26,10 +26,6 @@
 #include <stdio.h>
 #include <sys/mman.h>
 
-#ifdef __serenity__
-#    include <serenity.h>
-#endif
-
 namespace Gfx {
 
 struct BackingStore {
@@ -85,7 +81,6 @@ RefPtr<Bitmap> Bitmap::create_purgeable(BitmapFormat format, const IntSize& size
     return adopt_ref(*new Bitmap(format, size, scale_factor, Purgeable::Yes, backing_store.value()));
 }
 
-#ifdef __serenity__
 RefPtr<Bitmap> Bitmap::create_shareable(BitmapFormat format, const IntSize& size, int scale_factor)
 {
     if (size_would_overflow(format, size, scale_factor))
@@ -94,12 +89,11 @@ RefPtr<Bitmap> Bitmap::create_shareable(BitmapFormat format, const IntSize& size
     const auto pitch = minimum_pitch(size.width() * scale_factor, format);
     const auto data_size = size_in_bytes(pitch, size.height() * scale_factor);
 
-    auto anon_fd = anon_create(round_up_to_power_of_two(data_size, PAGE_SIZE), O_CLOEXEC);
-    if (anon_fd < 0)
+    auto buffer = Core::AnonymousBuffer::create_with_size(round_up_to_power_of_two(data_size, PAGE_SIZE));
+    if (!buffer.is_valid())
         return nullptr;
-    return Bitmap::create_with_anon_fd(format, anon_fd, size, scale_factor, {}, ShouldCloseAnonymousFile::No);
+    return Bitmap::create_with_anonymous_buffer(format, buffer, size, scale_factor, {});
 }
-#endif
 
 Bitmap::Bitmap(BitmapFormat format, const IntSize& size, int scale_factor, Purgeable purgeable, const BackingStore& backing_store)
     : m_size(size)
@@ -194,33 +188,12 @@ static bool check_size(const IntSize& size, int scale_factor, BitmapFormat forma
     return true;
 }
 
-RefPtr<Bitmap> Bitmap::create_with_anon_fd(BitmapFormat format, int anon_fd, const IntSize& size, int scale_factor, const Vector<RGBA32>& palette, ShouldCloseAnonymousFile should_close_anon_fd)
+RefPtr<Bitmap> Bitmap::create_with_anonymous_buffer(BitmapFormat format, Core::AnonymousBuffer buffer, const IntSize& size, int scale_factor, const Vector<RGBA32>& palette)
 {
-    void* data = nullptr;
-    {
-        // If ShouldCloseAnonymousFile::Yes, it's our responsibility to close 'anon_fd' no matter what.
-        ScopeGuard close_guard = [&] {
-            if (should_close_anon_fd == ShouldCloseAnonymousFile::Yes) {
-                int rc = close(anon_fd);
-                VERIFY(rc == 0);
-                anon_fd = -1;
-            }
-        };
-
-        if (size_would_overflow(format, size, scale_factor))
-            return nullptr;
-
-        const auto pitch = minimum_pitch(size.width() * scale_factor, format);
-        const auto data_size_in_bytes = size_in_bytes(pitch, size.height() * scale_factor);
-
-        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 (size_would_overflow(format, size, scale_factor))
+        return nullptr;
 
-    return adopt_ref(*new Bitmap(format, anon_fd, size, scale_factor, data, palette));
+    return adopt_ref(*new Bitmap(format, buffer, size, scale_factor, palette));
 }
 
 /// Read a bitmap as described by:
@@ -310,15 +283,14 @@ ByteBuffer Bitmap::serialize_to_byte_buffer() const
     return buffer;
 }
 
-Bitmap::Bitmap(BitmapFormat format, int anon_fd, const IntSize& size, int scale_factor, void* data, const Vector<RGBA32>& palette)
+Bitmap::Bitmap(BitmapFormat format, Core::AnonymousBuffer buffer, const IntSize& size, int scale_factor, const Vector<RGBA32>& palette)
     : m_size(size)
     , m_scale(scale_factor)
-    , m_data(data)
+    , m_data(buffer.data<void>())
     , m_pitch(minimum_pitch(size.width() * scale_factor, format))
     , m_format(format)
-    , m_needs_munmap(true)
     , m_purgeable(true)
-    , m_anon_fd(anon_fd)
+    , m_buffer(buffer)
 {
     VERIFY(!is_indexed() || !palette.is_empty());
     VERIFY(!size_would_overflow(format, size, scale_factor));
@@ -522,21 +494,19 @@ RefPtr<Gfx::Bitmap> Bitmap::cropped(Gfx::IntRect crop) const
     return new_bitmap;
 }
 
-#ifdef __serenity__
-RefPtr<Bitmap> Bitmap::to_bitmap_backed_by_anon_fd() const
+RefPtr<Bitmap> Bitmap::to_bitmap_backed_by_anonymous_buffer() const
 {
-    if (m_anon_fd != -1)
+    if (m_buffer.is_valid())
         return *this;
-    auto anon_fd = anon_create(round_up_to_power_of_two(size_in_bytes(), PAGE_SIZE), O_CLOEXEC);
-    if (anon_fd < 0)
+    auto buffer = Core::AnonymousBuffer::create_with_size(round_up_to_power_of_two(size_in_bytes(), PAGE_SIZE));
+    if (!buffer.is_valid())
         return nullptr;
-    auto bitmap = Bitmap::create_with_anon_fd(m_format, anon_fd, size(), scale(), palette_to_vector(), ShouldCloseAnonymousFile::No);
+    auto bitmap = Bitmap::create_with_anonymous_buffer(m_format, buffer, size(), scale(), palette_to_vector());
     if (!bitmap)
         return nullptr;
     memcpy(bitmap->scanline(0), scanline(0), size_in_bytes());
     return bitmap;
 }
-#endif
 
 Bitmap::~Bitmap()
 {
@@ -544,10 +514,6 @@ Bitmap::~Bitmap()
         int rc = munmap(m_data, size_in_bytes());
         VERIFY(rc == 0);
     }
-    if (m_anon_fd != -1) {
-        int rc = close(m_anon_fd);
-        VERIFY(rc == 0);
-    }
     m_data = nullptr;
     delete[] m_palette;
 }
@@ -602,15 +568,13 @@ void Bitmap::set_volatile()
     return rc == 0;
 }
 
-#ifdef __serenity__
 ShareableBitmap Bitmap::to_shareable_bitmap() const
 {
-    auto bitmap = to_bitmap_backed_by_anon_fd();
+    auto bitmap = to_bitmap_backed_by_anonymous_buffer();
     if (!bitmap)
         return {};
     return ShareableBitmap(*bitmap);
 }
-#endif
 
 Optional<BackingStore> Bitmap::allocate_backing_store(BitmapFormat format, const IntSize& size, int scale_factor, [[maybe_unused]] Purgeable purgeable)
 {

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

@@ -9,6 +9,7 @@
 #include <AK/Forward.h>
 #include <AK/RefCounted.h>
 #include <AK/RefPtr.h>
+#include <LibCore/AnonymousBuffer.h>
 #include <LibGfx/Color.h>
 #include <LibGfx/Forward.h>
 #include <LibGfx/Rect.h>
@@ -89,17 +90,12 @@ enum RotationDirection {
 
 class Bitmap : public RefCounted<Bitmap> {
 public:
-    enum class ShouldCloseAnonymousFile {
-        No,
-        Yes,
-    };
-
     static RefPtr<Bitmap> create(BitmapFormat, const IntSize&, int intrinsic_scale = 1);
     static RefPtr<Bitmap> create_shareable(BitmapFormat, const IntSize&, int intrinsic_scale = 1);
     static RefPtr<Bitmap> create_purgeable(BitmapFormat, const IntSize&, int intrinsic_scale = 1);
     static RefPtr<Bitmap> create_wrapper(BitmapFormat, const IntSize&, int intrinsic_scale, size_t pitch, void*);
     static RefPtr<Bitmap> load_from_file(String const& path, int scale_factor = 1);
-    static RefPtr<Bitmap> create_with_anon_fd(BitmapFormat, int anon_fd, const IntSize&, int intrinsic_scale, const Vector<RGBA32>& palette, ShouldCloseAnonymousFile);
+    static RefPtr<Bitmap> create_with_anonymous_buffer(BitmapFormat, Core::AnonymousBuffer, const IntSize&, int intrinsic_scale, const Vector<RGBA32>& palette);
     static RefPtr<Bitmap> create_from_serialized_byte_buffer(ByteBuffer&& buffer);
     static bool is_path_a_supported_image_format(const StringView& path)
     {
@@ -119,7 +115,7 @@ public:
     RefPtr<Gfx::Bitmap> scaled(int sx, int sy) const;
     RefPtr<Gfx::Bitmap> scaled(float sx, float sy) const;
     RefPtr<Gfx::Bitmap> cropped(Gfx::IntRect) const;
-    RefPtr<Bitmap> to_bitmap_backed_by_anon_fd() const;
+    RefPtr<Bitmap> to_bitmap_backed_by_anonymous_buffer() const;
     ByteBuffer serialize_to_byte_buffer() const;
 
     ShareableBitmap to_shareable_bitmap() const;
@@ -234,7 +230,8 @@ public:
     void set_volatile();
     [[nodiscard]] bool set_nonvolatile();
 
-    int anon_fd() const { return m_anon_fd; }
+    Core::AnonymousBuffer& anonymous_buffer() { return m_buffer; }
+    const Core::AnonymousBuffer& anonymous_buffer() const { return m_buffer; }
 
 private:
     enum class Purgeable {
@@ -243,7 +240,7 @@ private:
     };
     Bitmap(BitmapFormat, const IntSize&, int, Purgeable, const BackingStore&);
     Bitmap(BitmapFormat, const IntSize&, int, size_t pitch, void*);
-    Bitmap(BitmapFormat, int anon_fd, const IntSize&, int, void*, const Vector<RGBA32>& palette);
+    Bitmap(BitmapFormat, Core::AnonymousBuffer, const IntSize&, int, const Vector<RGBA32>& palette);
 
     static Optional<BackingStore> allocate_backing_store(BitmapFormat, const IntSize&, int, Purgeable);
 
@@ -258,7 +255,7 @@ private:
     bool m_needs_munmap { false };
     bool m_purgeable { false };
     bool m_volatile { false };
-    int m_anon_fd { -1 };
+    Core::AnonymousBuffer m_buffer;
 };
 
 inline u8* Bitmap::scanline_u8(int y)

+ 6 - 3
Userland/Libraries/LibGfx/ShareableBitmap.cpp

@@ -14,7 +14,7 @@
 namespace Gfx {
 
 ShareableBitmap::ShareableBitmap(const Bitmap& bitmap)
-    : m_bitmap(bitmap.to_bitmap_backed_by_anon_fd())
+    : m_bitmap(bitmap.to_bitmap_backed_by_anonymous_buffer())
 {
 }
 
@@ -33,7 +33,7 @@ bool encode(Encoder& encoder, const Gfx::ShareableBitmap& shareable_bitmap)
     if (!shareable_bitmap.is_valid())
         return true;
     auto& bitmap = *shareable_bitmap.bitmap();
-    encoder << IPC::File(bitmap.anon_fd());
+    encoder << IPC::File(bitmap.anonymous_buffer().fd());
     encoder << bitmap.size();
     encoder << bitmap.scale();
     encoder << (u32)bitmap.format();
@@ -73,7 +73,10 @@ bool decode(Decoder& decoder, Gfx::ShareableBitmap& shareable_bitmap)
         if (!decoder.decode(palette))
             return false;
     }
-    auto bitmap = Gfx::Bitmap::create_with_anon_fd(bitmap_format, anon_file.take_fd(), size, scale, palette, Gfx::Bitmap::ShouldCloseAnonymousFile::Yes);
+    auto buffer = Core::AnonymousBuffer::create_from_anon_fd(anon_file.take_fd(), Gfx::Bitmap::size_in_bytes(Gfx::Bitmap::minimum_pitch(size.width(), bitmap_format), size.height()));
+    if (!buffer.is_valid())
+        return false;
+    auto bitmap = Gfx::Bitmap::create_with_anonymous_buffer(bitmap_format, buffer, size, scale, palette);
     if (!bitmap)
         return false;
     shareable_bitmap = Gfx::ShareableBitmap { bitmap.release_nonnull(), Gfx::ShareableBitmap::ConstructWithKnownGoodBitmap };

+ 8 - 5
Userland/Services/WindowServer/ClientConnection.cpp

@@ -20,7 +20,6 @@
 #include <WindowServer/WindowManager.h>
 #include <WindowServer/WindowSwitcher.h>
 #include <errno.h>
-#include <serenity.h>
 #include <stdio.h>
 #include <unistd.h>
 
@@ -587,13 +586,17 @@ void ClientConnection::set_window_backing_store(i32 window_id, [[maybe_unused]]
         window.swap_backing_stores();
     } else {
         // FIXME: Plumb scale factor here eventually.
-        auto backing_store = Gfx::Bitmap::create_with_anon_fd(
+        Core::AnonymousBuffer buffer = Core::AnonymousBuffer::create_from_anon_fd(anon_file.take_fd(), pitch * size.height());
+        if (!buffer.is_valid()) {
+            did_misbehave("SetWindowBackingStore: Failed to create anonymous buffer for window backing store");
+            return;
+        }
+        auto backing_store = Gfx::Bitmap::create_with_anonymous_buffer(
             has_alpha_channel ? Gfx::BitmapFormat::BGRA8888 : Gfx::BitmapFormat::BGRx8888,
-            anon_file.take_fd(),
+            buffer,
             size,
             1,
-            {},
-            Gfx::Bitmap::ShouldCloseAnonymousFile::Yes);
+            {});
         window.set_backing_store(move(backing_store), serial);
     }