mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-26 01:20:25 +00:00
LibGfx: Make Gfx::Bitmap::set_nonvolatile() report allocation failure
Making a bitmap non-volatile after being volatile may fail to allocate physical pages after the kernel stole the old pages in a purge. This is different from the pages being purged, but reallocated. In that case, they are simply replaced with zero-fill-on-demand pages as if they were freshly allocated.
This commit is contained in:
parent
24b5295b30
commit
143443e0b6
Notes:
sideshowbarker
2024-07-18 08:22:11 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/143443e0b64
23 changed files with 57 additions and 46 deletions
|
@ -410,8 +410,9 @@ void Window::handle_multi_paint_event(MultiPaintEvent& event)
|
|||
m_back_store = create_backing_store(event.window_size());
|
||||
VERIFY(m_back_store);
|
||||
} else if (m_double_buffering_enabled) {
|
||||
bool still_has_pixels = m_back_store->bitmap().set_nonvolatile();
|
||||
if (!still_has_pixels) {
|
||||
bool was_purged = false;
|
||||
bool bitmap_has_memory = m_back_store->bitmap().set_nonvolatile(was_purged);
|
||||
if (!bitmap_has_memory || was_purged) {
|
||||
m_back_store = create_backing_store(event.window_size());
|
||||
VERIFY(m_back_store);
|
||||
created_new_backing_store = true;
|
||||
|
@ -1015,7 +1016,9 @@ void Window::notify_state_changed(Badge<WindowServerConnection>, bool minimized,
|
|||
if (minimized || occluded) {
|
||||
store->bitmap().set_volatile();
|
||||
} else {
|
||||
if (!store->bitmap().set_nonvolatile()) {
|
||||
bool was_purged = false;
|
||||
bool bitmap_has_memory = store->bitmap().set_nonvolatile(was_purged);
|
||||
if (!bitmap_has_memory || was_purged) {
|
||||
store = nullptr;
|
||||
update();
|
||||
}
|
||||
|
|
|
@ -1367,11 +1367,11 @@ void BMPImageDecoderPlugin::set_volatile()
|
|||
m_context->bitmap->set_volatile();
|
||||
}
|
||||
|
||||
bool BMPImageDecoderPlugin::set_nonvolatile()
|
||||
bool BMPImageDecoderPlugin::set_nonvolatile(bool& was_purged)
|
||||
{
|
||||
if (!m_context->bitmap)
|
||||
return false;
|
||||
return m_context->bitmap->set_nonvolatile();
|
||||
return m_context->bitmap->set_nonvolatile(was_purged);
|
||||
}
|
||||
|
||||
bool BMPImageDecoderPlugin::sniff()
|
||||
|
|
|
@ -24,7 +24,7 @@ public:
|
|||
virtual IntSize size() override;
|
||||
virtual RefPtr<Gfx::Bitmap> bitmap() override;
|
||||
virtual void set_volatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
||||
virtual bool sniff() override;
|
||||
virtual bool is_animated() override;
|
||||
virtual size_t loop_count() override;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include <LibGfx/PNGLoader.h>
|
||||
#include <LibGfx/PPMLoader.h>
|
||||
#include <LibGfx/ShareableBitmap.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
|
@ -533,21 +533,27 @@ void Bitmap::set_volatile()
|
|||
m_volatile = true;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool Bitmap::set_nonvolatile()
|
||||
[[nodiscard]] bool Bitmap::set_nonvolatile(bool& was_purged)
|
||||
{
|
||||
if (!m_volatile)
|
||||
if (!m_volatile) {
|
||||
was_purged = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef __serenity__
|
||||
int rc = madvise(m_data, size_in_bytes(), MADV_SET_NONVOLATILE);
|
||||
if (rc < 0) {
|
||||
perror("madvise(MADV_SET_NONVOLATILE)");
|
||||
VERIFY_NOT_REACHED();
|
||||
if (errno == ENOMEM) {
|
||||
was_purged = was_purged_int;
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
int rc = 0;
|
||||
|
||||
perror("madvise(MADV_SET_NONVOLATILE)");
|
||||
}
|
||||
was_purged = rc != 0;
|
||||
#endif
|
||||
m_volatile = false;
|
||||
return rc == 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
ShareableBitmap Bitmap::to_shareable_bitmap() const
|
||||
|
@ -600,5 +606,4 @@ Vector<RGBA32> Bitmap::palette_to_vector() const
|
|||
vector.unchecked_append(palette_color(i).value());
|
||||
return vector;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -227,7 +227,10 @@ public:
|
|||
|
||||
[[nodiscard]] bool is_volatile() const { return m_volatile; }
|
||||
void set_volatile();
|
||||
[[nodiscard]] bool set_nonvolatile();
|
||||
|
||||
// Returns true if making the bitmap non-volatile succeeded. `was_purged` indicates status of contents.
|
||||
// Returns false if there was not enough memory.
|
||||
[[nodiscard]] bool set_nonvolatile(bool& was_purged);
|
||||
|
||||
[[nodiscard]] Core::AnonymousBuffer& anonymous_buffer() { return m_buffer; }
|
||||
[[nodiscard]] Core::AnonymousBuffer const& anonymous_buffer() const { return m_buffer; }
|
||||
|
|
|
@ -1014,11 +1014,11 @@ void DDSImageDecoderPlugin::set_volatile()
|
|||
m_context->bitmap->set_volatile();
|
||||
}
|
||||
|
||||
bool DDSImageDecoderPlugin::set_nonvolatile()
|
||||
bool DDSImageDecoderPlugin::set_nonvolatile(bool& was_purged)
|
||||
{
|
||||
if (!m_context->bitmap)
|
||||
return false;
|
||||
return m_context->bitmap->set_nonvolatile();
|
||||
return m_context->bitmap->set_nonvolatile(was_purged);
|
||||
}
|
||||
|
||||
bool DDSImageDecoderPlugin::sniff()
|
||||
|
|
|
@ -245,7 +245,7 @@ public:
|
|||
virtual IntSize size() override;
|
||||
virtual RefPtr<Gfx::Bitmap> bitmap() override;
|
||||
virtual void set_volatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
||||
virtual bool sniff() override;
|
||||
virtual bool is_animated() override;
|
||||
virtual size_t loop_count() override;
|
||||
|
|
|
@ -655,12 +655,11 @@ void GIFImageDecoderPlugin::set_volatile()
|
|||
}
|
||||
}
|
||||
|
||||
bool GIFImageDecoderPlugin::set_nonvolatile()
|
||||
bool GIFImageDecoderPlugin::set_nonvolatile(bool& was_purged)
|
||||
{
|
||||
if (!m_context->frame_buffer) {
|
||||
return true;
|
||||
}
|
||||
return m_context->frame_buffer->set_nonvolatile();
|
||||
if (!m_context->frame_buffer)
|
||||
return false;
|
||||
return m_context->frame_buffer->set_nonvolatile(was_purged);
|
||||
}
|
||||
|
||||
bool GIFImageDecoderPlugin::sniff()
|
||||
|
|
|
@ -24,7 +24,7 @@ public:
|
|||
virtual IntSize size() override;
|
||||
virtual RefPtr<Gfx::Bitmap> bitmap() override;
|
||||
virtual void set_volatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
||||
virtual bool sniff() override;
|
||||
virtual bool is_animated() override;
|
||||
virtual size_t loop_count() override;
|
||||
|
|
|
@ -352,11 +352,11 @@ void ICOImageDecoderPlugin::set_volatile()
|
|||
m_context->images[0].bitmap->set_volatile();
|
||||
}
|
||||
|
||||
bool ICOImageDecoderPlugin::set_nonvolatile()
|
||||
bool ICOImageDecoderPlugin::set_nonvolatile(bool& was_purged)
|
||||
{
|
||||
if (!m_context->images[0].bitmap)
|
||||
return false;
|
||||
return m_context->images[0].bitmap->set_nonvolatile();
|
||||
return m_context->images[0].bitmap->set_nonvolatile(was_purged);
|
||||
}
|
||||
|
||||
bool ICOImageDecoderPlugin::sniff()
|
||||
|
|
|
@ -24,7 +24,7 @@ public:
|
|||
virtual IntSize size() override;
|
||||
virtual RefPtr<Gfx::Bitmap> bitmap() override;
|
||||
virtual void set_volatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
||||
virtual bool sniff() override;
|
||||
virtual bool is_animated() override;
|
||||
virtual size_t loop_count() override;
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
virtual RefPtr<Gfx::Bitmap> bitmap() = 0;
|
||||
|
||||
virtual void set_volatile() = 0;
|
||||
[[nodiscard]] virtual bool set_nonvolatile() = 0;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) = 0;
|
||||
|
||||
virtual bool sniff() = 0;
|
||||
|
||||
|
@ -63,7 +63,7 @@ public:
|
|||
if (m_plugin)
|
||||
m_plugin->set_volatile();
|
||||
}
|
||||
[[nodiscard]] bool set_nonvolatile() { return m_plugin ? m_plugin->set_nonvolatile() : false; }
|
||||
[[nodiscard]] bool set_nonvolatile(bool& was_purged) { return m_plugin ? m_plugin->set_nonvolatile(was_purged) : false; }
|
||||
bool sniff() const { return m_plugin ? m_plugin->sniff() : false; }
|
||||
bool is_animated() const { return m_plugin ? m_plugin->is_animated() : false; }
|
||||
size_t loop_count() const { return m_plugin ? m_plugin->loop_count() : 0; }
|
||||
|
|
|
@ -1295,11 +1295,11 @@ void JPGImageDecoderPlugin::set_volatile()
|
|||
m_context->bitmap->set_volatile();
|
||||
}
|
||||
|
||||
bool JPGImageDecoderPlugin::set_nonvolatile()
|
||||
bool JPGImageDecoderPlugin::set_nonvolatile(bool& was_purged)
|
||||
{
|
||||
if (!m_context->bitmap)
|
||||
return false;
|
||||
return m_context->bitmap->set_nonvolatile();
|
||||
return m_context->bitmap->set_nonvolatile(was_purged);
|
||||
}
|
||||
|
||||
bool JPGImageDecoderPlugin::sniff()
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
virtual IntSize size() override;
|
||||
virtual RefPtr<Gfx::Bitmap> bitmap() override;
|
||||
virtual void set_volatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
||||
virtual bool sniff() override;
|
||||
virtual bool is_animated() override;
|
||||
virtual size_t loop_count() override;
|
||||
|
|
|
@ -156,12 +156,12 @@ void PBMImageDecoderPlugin::set_volatile()
|
|||
m_context->bitmap->set_volatile();
|
||||
}
|
||||
|
||||
bool PBMImageDecoderPlugin::set_nonvolatile()
|
||||
bool PBMImageDecoderPlugin::set_nonvolatile(bool& was_purged)
|
||||
{
|
||||
if (!m_context->bitmap)
|
||||
return false;
|
||||
|
||||
return m_context->bitmap->set_nonvolatile();
|
||||
return m_context->bitmap->set_nonvolatile(was_purged);
|
||||
}
|
||||
|
||||
bool PBMImageDecoderPlugin::sniff()
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
virtual RefPtr<Gfx::Bitmap> bitmap() override;
|
||||
|
||||
virtual void set_volatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
||||
|
||||
virtual bool sniff() override;
|
||||
|
||||
|
|
|
@ -159,12 +159,12 @@ void PGMImageDecoderPlugin::set_volatile()
|
|||
m_context->bitmap->set_volatile();
|
||||
}
|
||||
|
||||
bool PGMImageDecoderPlugin::set_nonvolatile()
|
||||
bool PGMImageDecoderPlugin::set_nonvolatile(bool& was_purged)
|
||||
{
|
||||
if (!m_context->bitmap)
|
||||
return false;
|
||||
|
||||
return m_context->bitmap->set_nonvolatile();
|
||||
return m_context->bitmap->set_nonvolatile(was_purged);
|
||||
}
|
||||
|
||||
bool PGMImageDecoderPlugin::sniff()
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
virtual RefPtr<Gfx::Bitmap> bitmap() override;
|
||||
|
||||
virtual void set_volatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
||||
|
||||
virtual bool sniff() override;
|
||||
|
||||
|
|
|
@ -984,11 +984,11 @@ void PNGImageDecoderPlugin::set_volatile()
|
|||
m_context->bitmap->set_volatile();
|
||||
}
|
||||
|
||||
bool PNGImageDecoderPlugin::set_nonvolatile()
|
||||
bool PNGImageDecoderPlugin::set_nonvolatile(bool& was_purged)
|
||||
{
|
||||
if (!m_context->bitmap)
|
||||
return false;
|
||||
return m_context->bitmap->set_nonvolatile();
|
||||
return m_context->bitmap->set_nonvolatile(was_purged);
|
||||
}
|
||||
|
||||
bool PNGImageDecoderPlugin::sniff()
|
||||
|
|
|
@ -24,7 +24,7 @@ public:
|
|||
virtual IntSize size() override;
|
||||
virtual RefPtr<Gfx::Bitmap> bitmap() override;
|
||||
virtual void set_volatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
||||
virtual bool sniff() override;
|
||||
virtual bool is_animated() override;
|
||||
virtual size_t loop_count() override;
|
||||
|
|
|
@ -161,12 +161,12 @@ void PPMImageDecoderPlugin::set_volatile()
|
|||
m_context->bitmap->set_volatile();
|
||||
}
|
||||
|
||||
bool PPMImageDecoderPlugin::set_nonvolatile()
|
||||
bool PPMImageDecoderPlugin::set_nonvolatile(bool& was_purged)
|
||||
{
|
||||
if (!m_context->bitmap)
|
||||
return false;
|
||||
|
||||
return m_context->bitmap->set_nonvolatile();
|
||||
return m_context->bitmap->set_nonvolatile(was_purged);
|
||||
}
|
||||
|
||||
bool PPMImageDecoderPlugin::sniff()
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
virtual RefPtr<Gfx::Bitmap> bitmap() override;
|
||||
|
||||
virtual void set_volatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
||||
|
||||
virtual bool sniff() override;
|
||||
|
||||
|
|
|
@ -97,8 +97,9 @@ void ImageResource::update_volatility()
|
|||
if (!frame.bitmap) {
|
||||
still_has_decoded_image = false;
|
||||
} else {
|
||||
bool still_has_frame = frame.bitmap->set_nonvolatile();
|
||||
if (!still_has_frame)
|
||||
bool was_purged = false;
|
||||
bool bitmap_has_memory = frame.bitmap->set_nonvolatile(was_purged);
|
||||
if (!bitmap_has_memory || was_purged)
|
||||
still_has_decoded_image = false;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue