From 1db1ef9ea904390a6fe217c0a3244bf39dfdc056 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 28 Apr 2024 12:40:55 +0200 Subject: [PATCH] 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. --- Userland/Libraries/LibGfx/Bitmap.cpp | 24 +++++++++--------------- Userland/Libraries/LibGfx/Bitmap.h | 2 +- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/Userland/Libraries/LibGfx/Bitmap.cpp b/Userland/Libraries/LibGfx/Bitmap.cpp index a174c58c8b5..f9a38cd242e 100644 --- a/Userland/Libraries/LibGfx/Bitmap.cpp +++ b/Userland/Libraries/LibGfx/Bitmap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2023, Andreas Kling + * Copyright (c) 2018-2024, Andreas Kling * Copyright (c) 2022, Timothy Slater * * SPDX-License-Identifier: BSD-2-Clause @@ -23,9 +23,7 @@ #include #include #include -#include #include -#include 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> Bitmap::create_wrapper(BitmapFormat format, IntSize size, int scale_factor, size_t pitch, void* data) @@ -550,9 +548,8 @@ ErrorOr> 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 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 }; } diff --git a/Userland/Libraries/LibGfx/Bitmap.h b/Userland/Libraries/LibGfx/Bitmap.h index 9fe56beb90c..4c530c5164e 100644 --- a/Userland/Libraries/LibGfx/Bitmap.h +++ b/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; };