summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-07-24 22:49:48 +0200
committerAndreas Kling <kling@serenityos.org>2021-07-25 14:39:25 +0200
commit143443e0b6412cd7f5a702e5b190bea60da733fe (patch)
tree5d1490936ab7a056db804c4ba5ffd22558afa429 /Userland/Libraries
parent24b5295b3038dc0b7a49367476b5b8594268163d (diff)
downloadserenity-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')
-rw-r--r--Userland/Libraries/LibGUI/Window.cpp9
-rw-r--r--Userland/Libraries/LibGfx/BMPLoader.cpp4
-rw-r--r--Userland/Libraries/LibGfx/BMPLoader.h2
-rw-r--r--Userland/Libraries/LibGfx/Bitmap.cpp21
-rw-r--r--Userland/Libraries/LibGfx/Bitmap.h5
-rw-r--r--Userland/Libraries/LibGfx/DDSLoader.cpp4
-rw-r--r--Userland/Libraries/LibGfx/DDSLoader.h2
-rw-r--r--Userland/Libraries/LibGfx/GIFLoader.cpp9
-rw-r--r--Userland/Libraries/LibGfx/GIFLoader.h2
-rw-r--r--Userland/Libraries/LibGfx/ICOLoader.cpp4
-rw-r--r--Userland/Libraries/LibGfx/ICOLoader.h2
-rw-r--r--Userland/Libraries/LibGfx/ImageDecoder.h4
-rw-r--r--Userland/Libraries/LibGfx/JPGLoader.cpp4
-rw-r--r--Userland/Libraries/LibGfx/JPGLoader.h2
-rw-r--r--Userland/Libraries/LibGfx/PBMLoader.cpp4
-rw-r--r--Userland/Libraries/LibGfx/PBMLoader.h2
-rw-r--r--Userland/Libraries/LibGfx/PGMLoader.cpp4
-rw-r--r--Userland/Libraries/LibGfx/PGMLoader.h2
-rw-r--r--Userland/Libraries/LibGfx/PNGLoader.cpp4
-rw-r--r--Userland/Libraries/LibGfx/PNGLoader.h2
-rw-r--r--Userland/Libraries/LibGfx/PPMLoader.cpp4
-rw-r--r--Userland/Libraries/LibGfx/PPMLoader.h2
-rw-r--r--Userland/Libraries/LibWeb/Loader/ImageResource.cpp5
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;
}
}