summaryrefslogtreecommitdiff
path: root/Libraries/LibGfx
diff options
context:
space:
mode:
authorPeter Nelson <peter@peterdn.com>2020-09-12 17:17:50 +0100
committerAndreas Kling <kling@serenityos.org>2020-09-12 20:26:14 +0200
commitd366e996dd9a78c7a00bf7a41de6d7fa2c736aab (patch)
tree3ee24deeedc623cd3f01045cdecbb8920b46fa9e /Libraries/LibGfx
parent06eea59a65d90918bb4f064163d290413e29d476 (diff)
downloadserenity-d366e996dd9a78c7a00bf7a41de6d7fa2c736aab.zip
LibGfx: restructure Bitmap ctor to expect an alloc'd backing store
Moves Bitmap backing store creation to the static create() methods. This backing store is then passed into the Bitmap constructor. This allows us correctly return nullptr from create() in the event that memory allocation fails.
Diffstat (limited to 'Libraries/LibGfx')
-rw-r--r--Libraries/LibGfx/Bitmap.cpp60
-rw-r--r--Libraries/LibGfx/Bitmap.h9
2 files changed, 49 insertions, 20 deletions
diff --git a/Libraries/LibGfx/Bitmap.cpp b/Libraries/LibGfx/Bitmap.cpp
index b5e8a8164c..581397dbb7 100644
--- a/Libraries/LibGfx/Bitmap.cpp
+++ b/Libraries/LibGfx/Bitmap.cpp
@@ -26,6 +26,7 @@
#include <AK/Checked.h>
#include <AK/Memory.h>
+#include <AK/Optional.h>
#include <AK/SharedBuffer.h>
#include <AK/String.h>
#include <LibGfx/BMPLoader.h>
@@ -44,6 +45,12 @@
namespace Gfx {
+struct BackingStore {
+ void* data { nullptr };
+ size_t pitch { 0 };
+ size_t size_in_bytes { 0 };
+};
+
size_t Bitmap::minimum_pitch(size_t width, BitmapFormat format)
{
size_t element_size;
@@ -76,39 +83,32 @@ static bool size_would_overflow(BitmapFormat format, const IntSize& size)
RefPtr<Bitmap> Bitmap::create(BitmapFormat format, const IntSize& size)
{
- if (size_would_overflow(format, size))
+ auto backing_store = Bitmap::allocate_backing_store(format, size, Purgeable::No);
+ if (!backing_store.has_value())
return nullptr;
- return adopt(*new Bitmap(format, size, Purgeable::No));
+ return adopt(*new Bitmap(format, size, Purgeable::No, backing_store.value()));
}
RefPtr<Bitmap> Bitmap::create_purgeable(BitmapFormat format, const IntSize& size)
{
- if (size_would_overflow(format, size))
+ auto backing_store = Bitmap::allocate_backing_store(format, size, Purgeable::Yes);
+ if (!backing_store.has_value())
return nullptr;
- return adopt(*new Bitmap(format, size, Purgeable::Yes));
+ return adopt(*new Bitmap(format, size, Purgeable::Yes, backing_store.value()));
}
-Bitmap::Bitmap(BitmapFormat format, const IntSize& size, Purgeable purgeable)
+Bitmap::Bitmap(BitmapFormat format, const IntSize& size, Purgeable purgeable, const BackingStore& backing_store)
: m_size(size)
- , m_pitch(minimum_pitch(size.width(), format))
+ , m_data(backing_store.data)
+ , m_pitch(backing_store.pitch)
, m_format(format)
, m_purgeable(purgeable == Purgeable::Yes)
{
ASSERT(!m_size.is_empty());
ASSERT(!size_would_overflow(format, size));
- allocate_palette_from_format(format, {});
-#ifdef __serenity__
- int map_flags = purgeable == Purgeable::Yes ? (MAP_PURGEABLE | MAP_PRIVATE) : (MAP_ANONYMOUS | MAP_PRIVATE);
- m_data = mmap_with_name(nullptr, size_in_bytes(), PROT_READ | PROT_WRITE, map_flags, 0, 0, String::format("GraphicsBitmap [%dx%d]", width(), height()).characters());
-#else
- int map_flags = (MAP_ANONYMOUS | MAP_PRIVATE);
- m_data = mmap(nullptr, size_in_bytes(), PROT_READ | PROT_WRITE, map_flags, 0, 0);
-#endif
- if (m_data == MAP_FAILED) {
- perror("mmap");
- ASSERT_NOT_REACHED();
- }
ASSERT(m_data);
+ ASSERT(backing_store.size_in_bytes == size_in_bytes());
+ allocate_palette_from_format(format, {});
m_needs_munmap = true;
}
@@ -336,6 +336,30 @@ ShareableBitmap Bitmap::to_shareable_bitmap(pid_t peer_pid) const
return ShareableBitmap(*bitmap);
}
+Optional<BackingStore> Bitmap::allocate_backing_store(BitmapFormat format, const IntSize& size, Purgeable purgeable)
+{
+ if (size_would_overflow(format, size))
+ return {};
+
+ const auto pitch = minimum_pitch(size.width(), format);
+ const auto data_size_in_bytes = size_in_bytes(pitch, size.height());
+
+ void* data = nullptr;
+#ifdef __serenity__
+ int map_flags = purgeable == Purgeable::Yes ? (MAP_PURGEABLE | MAP_PRIVATE) : (MAP_ANONYMOUS | MAP_PRIVATE);
+ data = mmap_with_name(nullptr, data_size_in_bytes, PROT_READ | PROT_WRITE, map_flags, 0, 0, String::format("GraphicsBitmap [%dx%d]", size.width(), size.height()).characters());
+#else
+ UNUSED_PARAM(purgeable);
+ int map_flags = (MAP_ANONYMOUS | MAP_PRIVATE);
+ data = mmap(nullptr, data_size_in_bytes, PROT_READ | PROT_WRITE, map_flags, 0, 0);
+#endif
+ if (data == MAP_FAILED) {
+ perror("mmap");
+ return {};
+ }
+ return { { data, pitch, data_size_in_bytes } };
+}
+
void Bitmap::allocate_palette_from_format(BitmapFormat format, const Vector<RGBA32>& source_palette)
{
size_t size = palette_size(format);
diff --git a/Libraries/LibGfx/Bitmap.h b/Libraries/LibGfx/Bitmap.h
index 3a514543f5..66b42cf241 100644
--- a/Libraries/LibGfx/Bitmap.h
+++ b/Libraries/LibGfx/Bitmap.h
@@ -79,6 +79,8 @@ static StorageFormat determine_storage_format(BitmapFormat format)
}
}
+struct BackingStore;
+
enum RotationDirection {
Left,
Right
@@ -192,7 +194,8 @@ public:
void set_mmap_name(const StringView&);
- size_t size_in_bytes() const { return m_pitch * m_size.height(); }
+ static constexpr size_t size_in_bytes(size_t pitch, int height) { return pitch * height; }
+ size_t size_in_bytes() const { return size_in_bytes(m_pitch, height()); }
Color palette_color(u8 index) const { return Color::from_rgba(m_palette[index]); }
void set_palette_color(u8 index, Color color) { m_palette[index] = color.value(); }
@@ -223,10 +226,12 @@ private:
No,
Yes
};
- Bitmap(BitmapFormat, const IntSize&, Purgeable);
+ Bitmap(BitmapFormat, const IntSize&, Purgeable, const BackingStore&);
Bitmap(BitmapFormat, const IntSize&, size_t pitch, void*);
Bitmap(BitmapFormat, NonnullRefPtr<SharedBuffer>&&, const IntSize&, const Vector<RGBA32>& palette);
+ static Optional<BackingStore> allocate_backing_store(BitmapFormat, const IntSize&, Purgeable);
+
void allocate_palette_from_format(BitmapFormat, const Vector<RGBA32>& source_palette);
IntSize m_size;