diff options
author | Andreas Kling <kling@serenityos.org> | 2021-07-24 22:58:53 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-07-25 14:39:28 +0200 |
commit | 6bb53d6a80c9bc7e88876fa6774a253aa0ec2af5 (patch) | |
tree | e3ed22561cbe35bcc9f588e062e61abac6fbb57e /Userland | |
parent | 143443e0b6412cd7f5a702e5b190bea60da733fe (diff) | |
download | serenity-6bb53d6a80c9bc7e88876fa6774a253aa0ec2af5.zip |
LibGUI: Handle GUI::Window non-volatile backing store issues better
Instead of crashing when we can't make the back buffer non-volatile,
we now transition the window into single-buffered mode instead
(assuming it was originally in double-buffered mode.)
This reduces GUI fidelity a bit (by potentially making windows flicker
during repaint) but since it's only triggered in low-memory conditions,
it seems like a reasonable thing to sacrifice in order for the system
to carry on.
This patch also stops us from allocating entirely new backing stores
after the old ones were purged. If they were purged but reallocated
just fine, there's no need to allocate new memory again. We already
have fresh zero-filled pages in the existing bitmap at this point.
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibGUI/Window.cpp | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/Userland/Libraries/LibGUI/Window.cpp b/Userland/Libraries/LibGUI/Window.cpp index e0c7068d30..6945cb230f 100644 --- a/Userland/Libraries/LibGUI/Window.cpp +++ b/Userland/Libraries/LibGUI/Window.cpp @@ -412,9 +412,19 @@ void Window::handle_multi_paint_event(MultiPaintEvent& event) } else if (m_double_buffering_enabled) { 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); + if (!bitmap_has_memory) { + // We didn't have enough memory to make the bitmap non-volatile! + // Fall back to single-buffered mode for this window. + // FIXME: Once we have a way to listen for system memory pressure notifications, + // it would be cool to transition back into double-buffered mode once + // the coast is clear. + dbgln("Not enough memory to make backing store non-volatile. Falling back to single-buffered mode."); + m_double_buffering_enabled = false; + m_back_store = move(m_front_store); + created_new_backing_store = true; + } else if (was_purged) { + // The backing store bitmap was cleared, but it does have memory. + // Act as if it's a new backing store so the entire window gets repainted. created_new_backing_store = true; } } @@ -1018,9 +1028,15 @@ void Window::notify_state_changed(Badge<WindowServerConnection>, bool minimized, } else { bool was_purged = false; bool bitmap_has_memory = store->bitmap().set_nonvolatile(was_purged); - if (!bitmap_has_memory || was_purged) { + if (!bitmap_has_memory) { + // Not enough memory to make the bitmap non-volatile. Lose the bitmap and schedule an update. + // Let the paint system figure out what to do. store = nullptr; update(); + } else if (was_purged) { + // The bitmap memory was purged by the kernel, but we have all-new zero-filled pages. + // Schedule an update to regenerate the bitmap. + update(); } } } |