WindowServer: Add a mode for running without buffer flipping

We can't rely on all hardware to give us a way to flip between the back
and front buffer.

This mode should actually perform slightly better but may show some tearing
as we don't have a way to know when we're in vertical retrace.
This commit is contained in:
Andreas Kling 2019-08-15 15:08:32 +02:00
parent 2349dc1a21
commit 14888bd992
Notes: sideshowbarker 2024-07-19 12:40:40 +09:00
2 changed files with 35 additions and 6 deletions

View File

@ -33,7 +33,11 @@ WSCompositor::WSCompositor()
{
auto size = WSScreen::the().size();
m_front_bitmap = GraphicsBitmap::create_wrapper(GraphicsBitmap::Format::RGB32, size, WSScreen::the().scanline(0));
m_back_bitmap = GraphicsBitmap::create_wrapper(GraphicsBitmap::Format::RGB32, size, WSScreen::the().scanline(size.height()));
if (can_flip_buffers())
m_back_bitmap = GraphicsBitmap::create_wrapper(GraphicsBitmap::Format::RGB32, size, WSScreen::the().scanline(size.height()));
else
m_back_bitmap = GraphicsBitmap::create(GraphicsBitmap::Format::RGB32, size);
m_front_painter = make<Painter>(*m_front_bitmap);
m_back_painter = make<Painter>(*m_back_bitmap);
@ -168,7 +172,9 @@ void WSCompositor::compose()
m_front_painter->fill_rect(rect, Color::Yellow);
}
flip_buffers();
if (can_flip_buffers())
flip_buffers();
for (auto& r : dirty_rects.rects())
flush(r);
}
@ -181,14 +187,34 @@ void WSCompositor::flush(const Rect& a_rect)
dbgprintf("[WM] flush #%u (%d,%d %dx%d)\n", ++m_flush_count, rect.x(), rect.y(), rect.width(), rect.height());
#endif
const RGBA32* front_ptr = m_front_bitmap->scanline(rect.y()) + rect.x();
RGBA32* front_ptr = m_front_bitmap->scanline(rect.y()) + rect.x();
RGBA32* back_ptr = m_back_bitmap->scanline(rect.y()) + rect.x();
size_t pitch = m_back_bitmap->pitch();
// NOTE: The meaning of a flush depends on whether we can flip buffers or not.
//
// If flipping is supported, flushing means that we've flipped, and now we
// copy the changed bits from the front buffer to the back buffer, to keep
// them in sync.
//
// If flipping is not supported, flushing means that we copy the changed
// rects from the backing bitmap to the display framebuffer.
RGBA32* to_ptr;
const RGBA32* from_ptr;
if (can_flip_buffers()) {
to_ptr = back_ptr;
from_ptr = front_ptr;
} else {
to_ptr = front_ptr;
from_ptr = back_ptr;
}
for (int y = 0; y < rect.height(); ++y) {
fast_u32_copy(back_ptr, front_ptr, rect.width());
front_ptr = (const RGBA32*)((const u8*)front_ptr + pitch);
back_ptr = (RGBA32*)((u8*)back_ptr + pitch);
fast_u32_copy(to_ptr, from_ptr, rect.width());
from_ptr = (const RGBA32*)((const u8*)from_ptr + pitch);
to_ptr = (RGBA32*)((u8*)to_ptr + pitch);
}
}
@ -263,6 +289,7 @@ void WSCompositor::finish_setting_wallpaper(const String& path, NonnullRefPtr<Gr
void WSCompositor::flip_buffers()
{
ASSERT(can_flip_buffers());
swap(m_front_bitmap, m_back_bitmap);
swap(m_front_painter, m_back_painter);
int new_y_offset = m_buffers_are_flipped ? 0 : WSScreen::the().height();

View File

@ -35,6 +35,8 @@ public:
void invalidate_cursor();
Rect current_cursor_rect() const;
bool can_flip_buffers() const { return true; }
private:
WSCompositor();
void flip_buffers();