Browse Source

LibGfx: Make non-shared Bitmap used malloc() instead of mmap()

This drastically reduces the cost (in time AND space) of allocating
a Gfx::Bitmap.

Anything that needs to be shared is already using Core::AnonymousBuffer
anyway, so this shouldn't break anything important.

Do note that this makes it an error to create an empty (0x0) Bitmap,
which was previously allowed for some reason. Some small tweaks are
included to bail gracefully in such scenarios.
Andreas Kling 1 năm trước cách đây
mục cha
commit
1db1ef9ea9
2 tập tin đã thay đổi với 10 bổ sung16 xóa
  1. 9 15
      Userland/Libraries/LibGfx/Bitmap.cpp
  2. 1 1
      Userland/Libraries/LibGfx/Bitmap.h

+ 9 - 15
Userland/Libraries/LibGfx/Bitmap.cpp

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2023, Andreas Kling <kling@serenityos.org>
+ * Copyright (c) 2018-2024, Andreas Kling <kling@serenityos.org>
  * Copyright (c) 2022, Timothy Slater <tslater2006@gmail.com>
  *
  * SPDX-License-Identifier: BSD-2-Clause
@@ -23,9 +23,7 @@
 #include <LibGfx/ImageFormats/ImageDecoder.h>
 #include <LibGfx/ShareableBitmap.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <stdio.h>
-#include <sys/mman.h>
 
 namespace Gfx {
 
@@ -93,7 +91,7 @@ Bitmap::Bitmap(BitmapFormat format, IntSize size, int scale_factor, BackingStore
     VERIFY(!size_would_overflow(format, size, scale_factor));
     VERIFY(m_data);
     VERIFY(backing_store.size_in_bytes == size_in_bytes());
-    m_needs_munmap = true;
+    m_data_is_malloced = true;
 }
 
 ErrorOr<NonnullRefPtr<Bitmap>> Bitmap::create_wrapper(BitmapFormat format, IntSize size, int scale_factor, size_t pitch, void* data)
@@ -550,9 +548,8 @@ ErrorOr<NonnullRefPtr<Gfx::Bitmap>> Bitmap::inverted() const
 
 Bitmap::~Bitmap()
 {
-    if (m_needs_munmap) {
-        int rc = munmap(m_data, size_in_bytes());
-        VERIFY(rc == 0);
+    if (m_data_is_malloced) {
+        kfree_sized(m_data, size_in_bytes());
     }
     m_data = nullptr;
 }
@@ -583,20 +580,17 @@ Gfx::ShareableBitmap Bitmap::to_shareable_bitmap() const
 
 ErrorOr<BackingStore> Bitmap::allocate_backing_store(BitmapFormat format, IntSize size, int scale_factor)
 {
+    if (size.is_empty())
+        return Error::from_string_literal("Gfx::Bitmap backing store size is empty");
+
     if (size_would_overflow(format, size, scale_factor))
         return Error::from_string_literal("Gfx::Bitmap backing store size overflow");
 
     auto const pitch = minimum_pitch(size.width() * scale_factor, format);
     auto const data_size_in_bytes = size_in_bytes(pitch, size.height() * scale_factor);
 
-    int map_flags = MAP_ANONYMOUS | MAP_PRIVATE;
-#ifdef AK_OS_SERENITY
-    map_flags |= MAP_PURGEABLE;
-    void* data = mmap_with_name(nullptr, data_size_in_bytes, PROT_READ | PROT_WRITE, map_flags, 0, 0, ByteString::formatted("GraphicsBitmap [{}]", size).characters());
-#else
-    void* data = mmap(nullptr, data_size_in_bytes, PROT_READ | PROT_WRITE, map_flags, -1, 0);
-#endif
-    if (data == MAP_FAILED)
+    void* data = kcalloc(1, data_size_in_bytes);
+    if (data == nullptr)
         return Error::from_errno(errno);
     return BackingStore { data, pitch, data_size_in_bytes };
 }

+ 1 - 1
Userland/Libraries/LibGfx/Bitmap.h

@@ -244,7 +244,7 @@ private:
     void* m_data { nullptr };
     size_t m_pitch { 0 };
     BitmapFormat m_format { BitmapFormat::Invalid };
-    bool m_needs_munmap { false };
+    bool m_data_is_malloced { false };
     Core::AnonymousBuffer m_buffer;
 };