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 year ago
parent
commit
1db1ef9ea9
2 changed files with 10 additions and 16 deletions
  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>
  * Copyright (c) 2022, Timothy Slater <tslater2006@gmail.com>
  *
  *
  * SPDX-License-Identifier: BSD-2-Clause
  * SPDX-License-Identifier: BSD-2-Clause
@@ -23,9 +23,7 @@
 #include <LibGfx/ImageFormats/ImageDecoder.h>
 #include <LibGfx/ImageFormats/ImageDecoder.h>
 #include <LibGfx/ShareableBitmap.h>
 #include <LibGfx/ShareableBitmap.h>
 #include <errno.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <stdio.h>
 #include <stdio.h>
-#include <sys/mman.h>
 
 
 namespace Gfx {
 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(!size_would_overflow(format, size, scale_factor));
     VERIFY(m_data);
     VERIFY(m_data);
     VERIFY(backing_store.size_in_bytes == size_in_bytes());
     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)
 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()
 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;
     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)
 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))
     if (size_would_overflow(format, size, scale_factor))
         return Error::from_string_literal("Gfx::Bitmap backing store size overflow");
         return Error::from_string_literal("Gfx::Bitmap backing store size overflow");
 
 
     auto const pitch = minimum_pitch(size.width() * scale_factor, format);
     auto const pitch = minimum_pitch(size.width() * scale_factor, format);
     auto const data_size_in_bytes = size_in_bytes(pitch, size.height() * scale_factor);
     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 Error::from_errno(errno);
     return BackingStore { data, pitch, data_size_in_bytes };
     return BackingStore { data, pitch, data_size_in_bytes };
 }
 }

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

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