浏览代码

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 年之前
父节点
当前提交
1db1ef9ea9
共有 2 个文件被更改,包括 10 次插入16 次删除
  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;
 };