mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 21:57:43 +00:00
LibGfx: Remove "purgeable Gfx::Bitmap" as a separate concept
This was a really weird thing to begin with, purgeable bitmaps were basically regular bitmaps without a physical memory reservation. Since all the clients of this code ended up populating the bitmaps with pixels immediately after allocating them anyway, there was no need to avoid the reservation. Instead, all Gfx::Bitmaps are now purgeable, in the sense that they can be marked as volatile or non-volatile. The only difference here is that allocation failure is surfaced when we try to create the bitmap instead of during the handling of a subsequent page fault.
This commit is contained in:
parent
deec79b3c6
commit
24b5295b30
9 changed files with 17 additions and 44 deletions
|
@ -1185,7 +1185,7 @@ static bool decode_bmp_pixel_data(BMPLoadingContext& context)
|
||||||
|
|
||||||
const u32 width = abs(context.dib.core.width);
|
const u32 width = abs(context.dib.core.width);
|
||||||
const u32 height = abs(context.dib.core.height);
|
const u32 height = abs(context.dib.core.height);
|
||||||
context.bitmap = Bitmap::try_create_purgeable(format, { static_cast<int>(width), static_cast<int>(height) });
|
context.bitmap = Bitmap::try_create(format, { static_cast<int>(width), static_cast<int>(height) });
|
||||||
if (!context.bitmap) {
|
if (!context.bitmap) {
|
||||||
dbgln("BMP appears to have overly large dimensions");
|
dbgln("BMP appears to have overly large dimensions");
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -67,18 +67,10 @@ static bool size_would_overflow(BitmapFormat format, const IntSize& size, int sc
|
||||||
|
|
||||||
RefPtr<Bitmap> Bitmap::try_create(BitmapFormat format, const IntSize& size, int scale_factor)
|
RefPtr<Bitmap> Bitmap::try_create(BitmapFormat format, const IntSize& size, int scale_factor)
|
||||||
{
|
{
|
||||||
auto backing_store = Bitmap::try_allocate_backing_store(format, size, scale_factor, Purgeable::No);
|
auto backing_store = Bitmap::try_allocate_backing_store(format, size, scale_factor);
|
||||||
if (!backing_store.has_value())
|
if (!backing_store.has_value())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return adopt_ref(*new Bitmap(format, size, scale_factor, Purgeable::No, backing_store.value()));
|
return adopt_ref(*new Bitmap(format, size, scale_factor, backing_store.value()));
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<Bitmap> Bitmap::try_create_purgeable(BitmapFormat format, const IntSize& size, int scale_factor)
|
|
||||||
{
|
|
||||||
auto backing_store = Bitmap::try_allocate_backing_store(format, size, scale_factor, Purgeable::Yes);
|
|
||||||
if (!backing_store.has_value())
|
|
||||||
return nullptr;
|
|
||||||
return adopt_ref(*new Bitmap(format, size, scale_factor, Purgeable::Yes, backing_store.value()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<Bitmap> Bitmap::try_create_shareable(BitmapFormat format, const IntSize& size, int scale_factor)
|
RefPtr<Bitmap> Bitmap::try_create_shareable(BitmapFormat format, const IntSize& size, int scale_factor)
|
||||||
|
@ -95,13 +87,12 @@ RefPtr<Bitmap> Bitmap::try_create_shareable(BitmapFormat format, const IntSize&
|
||||||
return Bitmap::try_create_with_anonymous_buffer(format, buffer, size, scale_factor, {});
|
return Bitmap::try_create_with_anonymous_buffer(format, buffer, size, scale_factor, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
Bitmap::Bitmap(BitmapFormat format, const IntSize& size, int scale_factor, Purgeable purgeable, const BackingStore& backing_store)
|
Bitmap::Bitmap(BitmapFormat format, const IntSize& size, int scale_factor, const BackingStore& backing_store)
|
||||||
: m_size(size)
|
: m_size(size)
|
||||||
, m_scale(scale_factor)
|
, m_scale(scale_factor)
|
||||||
, m_data(backing_store.data)
|
, m_data(backing_store.data)
|
||||||
, m_pitch(backing_store.pitch)
|
, m_pitch(backing_store.pitch)
|
||||||
, m_format(format)
|
, m_format(format)
|
||||||
, m_purgeable(purgeable == Purgeable::Yes)
|
|
||||||
{
|
{
|
||||||
VERIFY(!m_size.is_empty());
|
VERIFY(!m_size.is_empty());
|
||||||
VERIFY(!size_would_overflow(format, size, scale_factor));
|
VERIFY(!size_would_overflow(format, size, scale_factor));
|
||||||
|
@ -289,7 +280,6 @@ Bitmap::Bitmap(BitmapFormat format, Core::AnonymousBuffer buffer, const IntSize&
|
||||||
, m_data(buffer.data<void>())
|
, m_data(buffer.data<void>())
|
||||||
, m_pitch(minimum_pitch(size.width() * scale_factor, format))
|
, m_pitch(minimum_pitch(size.width() * scale_factor, format))
|
||||||
, m_format(format)
|
, m_format(format)
|
||||||
, m_purgeable(true)
|
|
||||||
, m_buffer(move(buffer))
|
, m_buffer(move(buffer))
|
||||||
{
|
{
|
||||||
VERIFY(!is_indexed() || !palette.is_empty());
|
VERIFY(!is_indexed() || !palette.is_empty());
|
||||||
|
@ -301,16 +291,10 @@ Bitmap::Bitmap(BitmapFormat format, Core::AnonymousBuffer buffer, const IntSize&
|
||||||
|
|
||||||
RefPtr<Gfx::Bitmap> Bitmap::clone() const
|
RefPtr<Gfx::Bitmap> Bitmap::clone() const
|
||||||
{
|
{
|
||||||
RefPtr<Gfx::Bitmap> new_bitmap {};
|
auto new_bitmap = Bitmap::try_create(format(), size(), scale());
|
||||||
if (m_purgeable) {
|
|
||||||
new_bitmap = Bitmap::try_create_purgeable(format(), size(), scale());
|
|
||||||
} else {
|
|
||||||
new_bitmap = Bitmap::try_create(format(), size(), scale());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!new_bitmap) {
|
if (!new_bitmap)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
VERIFY(size_in_bytes() == new_bitmap->size_in_bytes());
|
VERIFY(size_in_bytes() == new_bitmap->size_in_bytes());
|
||||||
memcpy(new_bitmap->scanline(0), scanline(0), size_in_bytes());
|
memcpy(new_bitmap->scanline(0), scanline(0), size_in_bytes());
|
||||||
|
@ -537,7 +521,6 @@ void Bitmap::fill(Color color)
|
||||||
|
|
||||||
void Bitmap::set_volatile()
|
void Bitmap::set_volatile()
|
||||||
{
|
{
|
||||||
VERIFY(m_purgeable);
|
|
||||||
if (m_volatile)
|
if (m_volatile)
|
||||||
return;
|
return;
|
||||||
#ifdef __serenity__
|
#ifdef __serenity__
|
||||||
|
@ -552,7 +535,6 @@ void Bitmap::set_volatile()
|
||||||
|
|
||||||
[[nodiscard]] bool Bitmap::set_nonvolatile()
|
[[nodiscard]] bool Bitmap::set_nonvolatile()
|
||||||
{
|
{
|
||||||
VERIFY(m_purgeable);
|
|
||||||
if (!m_volatile)
|
if (!m_volatile)
|
||||||
return true;
|
return true;
|
||||||
#ifdef __serenity__
|
#ifdef __serenity__
|
||||||
|
@ -576,7 +558,7 @@ ShareableBitmap Bitmap::to_shareable_bitmap() const
|
||||||
return ShareableBitmap(*bitmap);
|
return ShareableBitmap(*bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<BackingStore> Bitmap::try_allocate_backing_store(BitmapFormat format, IntSize const& size, int scale_factor, [[maybe_unused]] Purgeable purgeable)
|
Optional<BackingStore> Bitmap::try_allocate_backing_store(BitmapFormat format, IntSize const& size, int scale_factor)
|
||||||
{
|
{
|
||||||
if (size_would_overflow(format, size, scale_factor))
|
if (size_would_overflow(format, size, scale_factor))
|
||||||
return {};
|
return {};
|
||||||
|
@ -585,8 +567,6 @@ Optional<BackingStore> Bitmap::try_allocate_backing_store(BitmapFormat format, I
|
||||||
const auto data_size_in_bytes = size_in_bytes(pitch, size.height() * scale_factor);
|
const auto data_size_in_bytes = size_in_bytes(pitch, size.height() * scale_factor);
|
||||||
|
|
||||||
int map_flags = MAP_ANONYMOUS | MAP_PRIVATE;
|
int map_flags = MAP_ANONYMOUS | MAP_PRIVATE;
|
||||||
if (purgeable == Purgeable::Yes)
|
|
||||||
map_flags |= MAP_NORESERVE;
|
|
||||||
#ifdef __serenity__
|
#ifdef __serenity__
|
||||||
void* data = mmap_with_name(nullptr, data_size_in_bytes, PROT_READ | PROT_WRITE, map_flags, 0, 0, String::formatted("GraphicsBitmap [{}]", size).characters());
|
void* data = mmap_with_name(nullptr, data_size_in_bytes, PROT_READ | PROT_WRITE, map_flags, 0, 0, String::formatted("GraphicsBitmap [{}]", size).characters());
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -92,7 +92,6 @@ class Bitmap : public RefCounted<Bitmap> {
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] static RefPtr<Bitmap> try_create(BitmapFormat, const IntSize&, int intrinsic_scale = 1);
|
[[nodiscard]] static RefPtr<Bitmap> try_create(BitmapFormat, const IntSize&, int intrinsic_scale = 1);
|
||||||
[[nodiscard]] static RefPtr<Bitmap> try_create_shareable(BitmapFormat, const IntSize&, int intrinsic_scale = 1);
|
[[nodiscard]] static RefPtr<Bitmap> try_create_shareable(BitmapFormat, const IntSize&, int intrinsic_scale = 1);
|
||||||
[[nodiscard]] static RefPtr<Bitmap> try_create_purgeable(BitmapFormat, const IntSize&, int intrinsic_scale = 1);
|
|
||||||
[[nodiscard]] static RefPtr<Bitmap> try_create_wrapper(BitmapFormat, const IntSize&, int intrinsic_scale, size_t pitch, void*);
|
[[nodiscard]] static RefPtr<Bitmap> try_create_wrapper(BitmapFormat, const IntSize&, int intrinsic_scale, size_t pitch, void*);
|
||||||
[[nodiscard]] static RefPtr<Bitmap> try_load_from_file(String const& path, int scale_factor = 1);
|
[[nodiscard]] static RefPtr<Bitmap> try_load_from_file(String const& path, int scale_factor = 1);
|
||||||
[[nodiscard]] static RefPtr<Bitmap> try_create_with_anonymous_buffer(BitmapFormat, Core::AnonymousBuffer, const IntSize&, int intrinsic_scale, const Vector<RGBA32>& palette);
|
[[nodiscard]] static RefPtr<Bitmap> try_create_with_anonymous_buffer(BitmapFormat, Core::AnonymousBuffer, const IntSize&, int intrinsic_scale, const Vector<RGBA32>& palette);
|
||||||
|
@ -226,7 +225,6 @@ public:
|
||||||
set_pixel(physical_position.x(), physical_position.y(), color);
|
set_pixel(physical_position.x(), physical_position.y(), color);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool is_purgeable() const { return m_purgeable; }
|
|
||||||
[[nodiscard]] bool is_volatile() const { return m_volatile; }
|
[[nodiscard]] bool is_volatile() const { return m_volatile; }
|
||||||
void set_volatile();
|
void set_volatile();
|
||||||
[[nodiscard]] bool set_nonvolatile();
|
[[nodiscard]] bool set_nonvolatile();
|
||||||
|
@ -235,15 +233,11 @@ public:
|
||||||
[[nodiscard]] Core::AnonymousBuffer const& anonymous_buffer() const { return m_buffer; }
|
[[nodiscard]] Core::AnonymousBuffer const& anonymous_buffer() const { return m_buffer; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class Purgeable {
|
Bitmap(BitmapFormat, IntSize const&, int, BackingStore const&);
|
||||||
No,
|
|
||||||
Yes
|
|
||||||
};
|
|
||||||
Bitmap(BitmapFormat, const IntSize&, int, Purgeable, const BackingStore&);
|
|
||||||
Bitmap(BitmapFormat, const IntSize&, int, size_t pitch, void*);
|
Bitmap(BitmapFormat, const IntSize&, int, size_t pitch, void*);
|
||||||
Bitmap(BitmapFormat, Core::AnonymousBuffer, const IntSize&, int, const Vector<RGBA32>& palette);
|
Bitmap(BitmapFormat, Core::AnonymousBuffer, const IntSize&, int, const Vector<RGBA32>& palette);
|
||||||
|
|
||||||
static Optional<BackingStore> try_allocate_backing_store(BitmapFormat format, IntSize const& size, int scale_factor, Purgeable);
|
static Optional<BackingStore> try_allocate_backing_store(BitmapFormat format, IntSize const& size, int scale_factor);
|
||||||
|
|
||||||
void allocate_palette_from_format(BitmapFormat, const Vector<RGBA32>& source_palette);
|
void allocate_palette_from_format(BitmapFormat, const Vector<RGBA32>& source_palette);
|
||||||
|
|
||||||
|
@ -254,7 +248,6 @@ private:
|
||||||
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_needs_munmap { false };
|
||||||
bool m_purgeable { false };
|
|
||||||
bool m_volatile { false };
|
bool m_volatile { false };
|
||||||
Core::AnonymousBuffer m_buffer;
|
Core::AnonymousBuffer m_buffer;
|
||||||
};
|
};
|
||||||
|
|
|
@ -792,7 +792,7 @@ static bool decode_dds(DDSLoadingContext& context)
|
||||||
dbgln_if(DDS_DEBUG, "There are {} bytes remaining, we need {} for mipmap level {} of the image", stream.remaining(), needed_bytes, mipmap_level);
|
dbgln_if(DDS_DEBUG, "There are {} bytes remaining, we need {} for mipmap level {} of the image", stream.remaining(), needed_bytes, mipmap_level);
|
||||||
VERIFY(stream.remaining() >= needed_bytes);
|
VERIFY(stream.remaining() >= needed_bytes);
|
||||||
|
|
||||||
context.bitmap = Bitmap::try_create_purgeable(BitmapFormat::BGRA8888, { width, height });
|
context.bitmap = Bitmap::try_create(BitmapFormat::BGRA8888, { width, height });
|
||||||
|
|
||||||
decode_bitmap(stream, context, format, width, height);
|
decode_bitmap(stream, context, format, width, height);
|
||||||
|
|
||||||
|
|
|
@ -299,10 +299,10 @@ static bool decode_frame(GIFLoadingContext& context, size_t frame_index)
|
||||||
size_t start_frame = context.current_frame + 1;
|
size_t start_frame = context.current_frame + 1;
|
||||||
if (context.state < GIFLoadingContext::State::FrameComplete) {
|
if (context.state < GIFLoadingContext::State::FrameComplete) {
|
||||||
start_frame = 0;
|
start_frame = 0;
|
||||||
context.frame_buffer = Bitmap::try_create_purgeable(BitmapFormat::BGRA8888, { context.logical_screen.width, context.logical_screen.height });
|
context.frame_buffer = Bitmap::try_create(BitmapFormat::BGRA8888, { context.logical_screen.width, context.logical_screen.height });
|
||||||
if (!context.frame_buffer)
|
if (!context.frame_buffer)
|
||||||
return false;
|
return false;
|
||||||
context.prev_frame_buffer = Bitmap::try_create_purgeable(BitmapFormat::BGRA8888, { context.logical_screen.width, context.logical_screen.height });
|
context.prev_frame_buffer = Bitmap::try_create(BitmapFormat::BGRA8888, { context.logical_screen.width, context.logical_screen.height });
|
||||||
if (!context.prev_frame_buffer)
|
if (!context.prev_frame_buffer)
|
||||||
return false;
|
return false;
|
||||||
} else if (frame_index < context.current_frame) {
|
} else if (frame_index < context.current_frame) {
|
||||||
|
|
|
@ -246,7 +246,7 @@ static bool load_ico_bmp(ICOLoadingContext& context, ICOImageDescriptor& desc)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
desc.bitmap = Bitmap::try_create_purgeable(BitmapFormat::BGRA8888, { desc.width, desc.height });
|
desc.bitmap = Bitmap::try_create(BitmapFormat::BGRA8888, { desc.width, desc.height });
|
||||||
if (!desc.bitmap)
|
if (!desc.bitmap)
|
||||||
return false;
|
return false;
|
||||||
Bitmap& bitmap = *desc.bitmap;
|
Bitmap& bitmap = *desc.bitmap;
|
||||||
|
|
|
@ -1064,7 +1064,7 @@ static void ycbcr_to_rgb(const JPGLoadingContext& context, Vector<Macroblock>& m
|
||||||
|
|
||||||
static bool compose_bitmap(JPGLoadingContext& context, const Vector<Macroblock>& macroblocks)
|
static bool compose_bitmap(JPGLoadingContext& context, const Vector<Macroblock>& macroblocks)
|
||||||
{
|
{
|
||||||
context.bitmap = Bitmap::try_create_purgeable(BitmapFormat::BGRx8888, { context.frame.width, context.frame.height });
|
context.bitmap = Bitmap::try_create(BitmapFormat::BGRx8888, { context.frame.width, context.frame.height });
|
||||||
if (!context.bitmap)
|
if (!context.bitmap)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -606,7 +606,7 @@ static bool decode_png_bitmap_simple(PNGLoadingContext& context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context.bitmap = Bitmap::try_create_purgeable(context.has_alpha() ? BitmapFormat::BGRA8888 : BitmapFormat::BGRx8888, { context.width, context.height });
|
context.bitmap = Bitmap::try_create(context.has_alpha() ? BitmapFormat::BGRA8888 : BitmapFormat::BGRx8888, { context.width, context.height });
|
||||||
|
|
||||||
if (!context.bitmap) {
|
if (!context.bitmap) {
|
||||||
context.state = PNGLoadingContext::State::Error;
|
context.state = PNGLoadingContext::State::Error;
|
||||||
|
@ -726,7 +726,7 @@ static bool decode_adam7_pass(PNGLoadingContext& context, Streamer& streamer, in
|
||||||
static bool decode_png_adam7(PNGLoadingContext& context)
|
static bool decode_png_adam7(PNGLoadingContext& context)
|
||||||
{
|
{
|
||||||
Streamer streamer(context.decompression_buffer->data(), context.decompression_buffer->size());
|
Streamer streamer(context.decompression_buffer->data(), context.decompression_buffer->size());
|
||||||
context.bitmap = Bitmap::try_create_purgeable(context.has_alpha() ? BitmapFormat::BGRA8888 : BitmapFormat::BGRx8888, { context.width, context.height });
|
context.bitmap = Bitmap::try_create(context.has_alpha() ? BitmapFormat::BGRA8888 : BitmapFormat::BGRx8888, { context.width, context.height });
|
||||||
if (!context.bitmap)
|
if (!context.bitmap)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -178,7 +178,7 @@ static bool read_max_val(TContext& context, Streamer& streamer)
|
||||||
template<typename TContext>
|
template<typename TContext>
|
||||||
static bool create_bitmap(TContext& context)
|
static bool create_bitmap(TContext& context)
|
||||||
{
|
{
|
||||||
context.bitmap = Bitmap::try_create_purgeable(BitmapFormat::BGRx8888, { context.width, context.height });
|
context.bitmap = Bitmap::try_create(BitmapFormat::BGRx8888, { context.width, context.height });
|
||||||
if (!context.bitmap) {
|
if (!context.bitmap) {
|
||||||
context.state = TContext::State::Error;
|
context.state = TContext::State::Error;
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue