diff options
author | Andreas Kling <kling@serenityos.org> | 2021-07-24 22:49:48 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-07-25 14:39:25 +0200 |
commit | 143443e0b6412cd7f5a702e5b190bea60da733fe (patch) | |
tree | 5d1490936ab7a056db804c4ba5ffd22558afa429 /Userland/Libraries | |
parent | 24b5295b3038dc0b7a49367476b5b8594268163d (diff) | |
download | serenity-143443e0b6412cd7f5a702e5b190bea60da733fe.zip |
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.
Diffstat (limited to 'Userland/Libraries')
23 files changed, 57 insertions, 46 deletions
diff --git a/Userland/Libraries/LibGUI/Window.cpp b/Userland/Libraries/LibGUI/Window.cpp index fe37f5ef0d..e0c7068d30 100644 --- a/Userland/Libraries/LibGUI/Window.cpp +++ b/Userland/Libraries/LibGUI/Window.cpp @@ -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(); } diff --git a/Userland/Libraries/LibGfx/BMPLoader.cpp b/Userland/Libraries/LibGfx/BMPLoader.cpp index f1dce58e75..69f8623a52 100644 --- a/Userland/Libraries/LibGfx/BMPLoader.cpp +++ b/Userland/Libraries/LibGfx/BMPLoader.cpp @@ -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() diff --git a/Userland/Libraries/LibGfx/BMPLoader.h b/Userland/Libraries/LibGfx/BMPLoader.h index 0a5f6c4f6e..c73e94857e 100644 --- a/Userland/Libraries/LibGfx/BMPLoader.h +++ b/Userland/Libraries/LibGfx/BMPLoader.h @@ -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; diff --git a/Userland/Libraries/LibGfx/Bitmap.cpp b/Userland/Libraries/LibGfx/Bitmap.cpp index 104aec4462..8d8f4b87b7 100644 --- a/Userland/Libraries/LibGfx/Bitmap.cpp +++ b/Userland/Libraries/LibGfx/Bitmap.cpp @@ -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) { + if (errno == ENOMEM) { + was_purged = was_purged_int; + return false; + } + perror("madvise(MADV_SET_NONVOLATILE)"); - VERIFY_NOT_REACHED(); } -#else - int rc = 0; + 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; } - } diff --git a/Userland/Libraries/LibGfx/Bitmap.h b/Userland/Libraries/LibGfx/Bitmap.h index 5481adb278..4436d56350 100644 --- a/Userland/Libraries/LibGfx/Bitmap.h +++ b/Userland/Libraries/LibGfx/Bitmap.h @@ -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; } diff --git a/Userland/Libraries/LibGfx/DDSLoader.cpp b/Userland/Libraries/LibGfx/DDSLoader.cpp index 5d0a22c31d..7289ed974b 100644 --- a/Userland/Libraries/LibGfx/DDSLoader.cpp +++ b/Userland/Libraries/LibGfx/DDSLoader.cpp @@ -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() diff --git a/Userland/Libraries/LibGfx/DDSLoader.h b/Userland/Libraries/LibGfx/DDSLoader.h index 8b5eab464b..4179a956d1 100644 --- a/Userland/Libraries/LibGfx/DDSLoader.h +++ b/Userland/Libraries/LibGfx/DDSLoader.h @@ -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; diff --git a/Userland/Libraries/LibGfx/GIFLoader.cpp b/Userland/Libraries/LibGfx/GIFLoader.cpp index fa47e9a0f8..ee4f2aa099 100644 --- a/Userland/Libraries/LibGfx/GIFLoader.cpp +++ b/Userland/Libraries/LibGfx/GIFLoader.cpp @@ -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() diff --git a/Userland/Libraries/LibGfx/GIFLoader.h b/Userland/Libraries/LibGfx/GIFLoader.h index 3c01d497c4..2227294e46 100644 --- a/Userland/Libraries/LibGfx/GIFLoader.h +++ b/Userland/Libraries/LibGfx/GIFLoader.h @@ -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; diff --git a/Userland/Libraries/LibGfx/ICOLoader.cpp b/Userland/Libraries/LibGfx/ICOLoader.cpp index ad94fe652e..969117e938 100644 --- a/Userland/Libraries/LibGfx/ICOLoader.cpp +++ b/Userland/Libraries/LibGfx/ICOLoader.cpp @@ -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() diff --git a/Userland/Libraries/LibGfx/ICOLoader.h b/Userland/Libraries/LibGfx/ICOLoader.h index 22f319c4db..f7fa88502a 100644 --- a/Userland/Libraries/LibGfx/ICOLoader.h +++ b/Userland/Libraries/LibGfx/ICOLoader.h @@ -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; diff --git a/Userland/Libraries/LibGfx/ImageDecoder.h b/Userland/Libraries/LibGfx/ImageDecoder.h index 0855673871..a22dc3b584 100644 --- a/Userland/Libraries/LibGfx/ImageDecoder.h +++ b/Userland/Libraries/LibGfx/ImageDecoder.h @@ -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; } diff --git a/Userland/Libraries/LibGfx/JPGLoader.cpp b/Userland/Libraries/LibGfx/JPGLoader.cpp index 9e0239e67a..3d424a28ab 100644 --- a/Userland/Libraries/LibGfx/JPGLoader.cpp +++ b/Userland/Libraries/LibGfx/JPGLoader.cpp @@ -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() diff --git a/Userland/Libraries/LibGfx/JPGLoader.h b/Userland/Libraries/LibGfx/JPGLoader.h index ca567eacdc..549eeee019 100644 --- a/Userland/Libraries/LibGfx/JPGLoader.h +++ b/Userland/Libraries/LibGfx/JPGLoader.h @@ -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; diff --git a/Userland/Libraries/LibGfx/PBMLoader.cpp b/Userland/Libraries/LibGfx/PBMLoader.cpp index b70580a03b..3dc89b991e 100644 --- a/Userland/Libraries/LibGfx/PBMLoader.cpp +++ b/Userland/Libraries/LibGfx/PBMLoader.cpp @@ -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() diff --git a/Userland/Libraries/LibGfx/PBMLoader.h b/Userland/Libraries/LibGfx/PBMLoader.h index e5657db655..06fd5ecb75 100644 --- a/Userland/Libraries/LibGfx/PBMLoader.h +++ b/Userland/Libraries/LibGfx/PBMLoader.h @@ -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; diff --git a/Userland/Libraries/LibGfx/PGMLoader.cpp b/Userland/Libraries/LibGfx/PGMLoader.cpp index 2df8a37dae..e3fe486029 100644 --- a/Userland/Libraries/LibGfx/PGMLoader.cpp +++ b/Userland/Libraries/LibGfx/PGMLoader.cpp @@ -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() diff --git a/Userland/Libraries/LibGfx/PGMLoader.h b/Userland/Libraries/LibGfx/PGMLoader.h index e9ad080a7a..bb2ab9c15b 100644 --- a/Userland/Libraries/LibGfx/PGMLoader.h +++ b/Userland/Libraries/LibGfx/PGMLoader.h @@ -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; diff --git a/Userland/Libraries/LibGfx/PNGLoader.cpp b/Userland/Libraries/LibGfx/PNGLoader.cpp index 760b0cba91..4129cec13c 100644 --- a/Userland/Libraries/LibGfx/PNGLoader.cpp +++ b/Userland/Libraries/LibGfx/PNGLoader.cpp @@ -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() diff --git a/Userland/Libraries/LibGfx/PNGLoader.h b/Userland/Libraries/LibGfx/PNGLoader.h index 6ae38c2543..49f5c17906 100644 --- a/Userland/Libraries/LibGfx/PNGLoader.h +++ b/Userland/Libraries/LibGfx/PNGLoader.h @@ -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; diff --git a/Userland/Libraries/LibGfx/PPMLoader.cpp b/Userland/Libraries/LibGfx/PPMLoader.cpp index c7434bf4a0..91cc921f8b 100644 --- a/Userland/Libraries/LibGfx/PPMLoader.cpp +++ b/Userland/Libraries/LibGfx/PPMLoader.cpp @@ -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() diff --git a/Userland/Libraries/LibGfx/PPMLoader.h b/Userland/Libraries/LibGfx/PPMLoader.h index 5de105101b..0e20adf3ab 100644 --- a/Userland/Libraries/LibGfx/PPMLoader.h +++ b/Userland/Libraries/LibGfx/PPMLoader.h @@ -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; diff --git a/Userland/Libraries/LibWeb/Loader/ImageResource.cpp b/Userland/Libraries/LibWeb/Loader/ImageResource.cpp index 1261559464..508bd62ba6 100644 --- a/Userland/Libraries/LibWeb/Loader/ImageResource.cpp +++ b/Userland/Libraries/LibWeb/Loader/ImageResource.cpp @@ -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; } } |