WindowServer: Fix caching stretched wallpaper for multiple screens

This creates a cached bitmap for each unique screen resolution, which
allows us to share it between displays with the same resolution. If
the resolution is the same as the wallpaper, we can just use the
wallpaper as-is.
This commit is contained in:
Tom 2023-02-17 20:57:08 -07:00 committed by Linus Groh
parent 5b77346f53
commit 15d4903efb
Notes: sideshowbarker 2024-07-17 10:16:43 +09:00
3 changed files with 33 additions and 15 deletions

View file

@ -840,28 +840,47 @@ void Compositor::update_wallpaper_bitmap()
screen_data.clear_wallpaper_bitmap();
return IterationDecision::Continue;
}
if (!screen_data.m_wallpaper_bitmap)
screen_data.init_wallpaper_bitmap(screen);
auto rect = screen_data.m_wallpaper_bitmap->rect();
auto& painter = *screen_data.m_wallpaper_painter;
// See if there is another screen with the same resolution and scale.
// If so, we can use the same bitmap.
bool share_bitmap_with_other_screen = false;
Screen::for_each([&](Screen& screen2) {
if (&screen == &screen2) {
// Stop iterating here, we haven't updated wallpaper bitmaps for
// this screen and the following screens.
return IterationDecision::Break;
}
painter.draw_scaled_bitmap(rect, *m_wallpaper, m_wallpaper->rect());
if (screen.size() == screen2.size() && screen.scale_factor() == screen2.scale_factor()) {
auto& screen2_data = screen2.compositor_screen_data();
// Use the same bitmap as the other screen
screen_data.m_wallpaper_bitmap = screen2_data.m_wallpaper_bitmap;
share_bitmap_with_other_screen = true;
return IterationDecision::Break;
}
return IterationDecision::Continue;
});
if (share_bitmap_with_other_screen)
return IterationDecision::Continue;
if (screen.size() == m_wallpaper->size() && screen.scale_factor() == m_wallpaper->scale()) {
// If the screen size is equal to the wallpaper size, we don't actually need to scale it
screen_data.m_wallpaper_bitmap = m_wallpaper;
} else {
if (!screen_data.m_wallpaper_bitmap)
screen_data.m_wallpaper_bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRx8888, screen.size(), screen.scale_factor()).release_value_but_fixme_should_propagate_errors();
Gfx::Painter painter(*screen_data.m_wallpaper_bitmap);
painter.draw_scaled_bitmap(screen_data.m_wallpaper_bitmap->rect(), *m_wallpaper, m_wallpaper->rect());
}
return IterationDecision::Continue;
});
}
void CompositorScreenData::init_wallpaper_bitmap(Screen& screen)
{
m_wallpaper_bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRx8888, screen.size(), screen.scale_factor()).release_value_but_fixme_should_propagate_errors();
m_wallpaper_painter = make<Gfx::Painter>(*m_wallpaper_bitmap);
m_wallpaper_painter->translate(-screen.rect().location());
}
void CompositorScreenData::clear_wallpaper_bitmap()
{
m_wallpaper_painter = nullptr;
m_wallpaper_bitmap = nullptr;
}

View file

@ -40,7 +40,6 @@ struct CompositorScreenData {
OwnPtr<Gfx::Painter> m_back_painter;
OwnPtr<Gfx::Painter> m_front_painter;
OwnPtr<Gfx::Painter> m_temp_painter;
OwnPtr<Gfx::Painter> m_wallpaper_painter;
RefPtr<Gfx::Bitmap> m_cursor_back_bitmap;
OwnPtr<Gfx::Painter> m_cursor_back_painter;
Gfx::IntRect m_last_cursor_rect;
@ -62,7 +61,6 @@ struct CompositorScreenData {
void flip_buffers(Screen&);
void draw_cursor(Screen&, Gfx::IntRect const&);
bool restore_cursor_back(Screen&, Gfx::IntRect&);
void init_wallpaper_bitmap(Screen&);
void clear_wallpaper_bitmap();
template<typename F>

View file

@ -164,6 +164,7 @@ public:
Gfx::IntSize physical_size() const { return { physical_width(), physical_height() }; }
Gfx::IntPoint location() const { return m_virtual_rect.location(); }
Gfx::IntSize size() const { return { m_virtual_rect.width(), m_virtual_rect.height() }; }
Gfx::IntRect rect() const { return m_virtual_rect; }