mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 13:47:45 +00:00
WindowServer: Use FB_IOCTL_FLUSH_HEAD to flush a framebuffer if possible
This ioctl is more appropriate when the hardware supports flushing of the entire framebuffer, so we use that instead of the previous default FB_IOCTL_FLUSH_HEAD_BUFFERS ioctl.
This commit is contained in:
parent
41283a2de6
commit
4ff6150f1b
8 changed files with 45 additions and 5 deletions
|
@ -98,4 +98,9 @@ ALWAYS_INLINE int fb_flush_buffers(int fd, int index, FBRect const* rects, unsig
|
|||
return ioctl(fd, FB_IOCTL_FLUSH_HEAD_BUFFERS, &fb_flush_rects);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE int fb_flush_head(int fd)
|
||||
{
|
||||
return ioctl(fd, FB_IOCTL_FLUSH_HEAD, nullptr);
|
||||
}
|
||||
|
||||
__END_DECLS
|
||||
|
|
|
@ -629,7 +629,9 @@ void Compositor::flush(Screen& screen)
|
|||
bounding_flash = bounding_flash.united(rect);
|
||||
}
|
||||
if (!bounding_flash.is_empty()) {
|
||||
if (device_can_flush_buffers) {
|
||||
if (screen.can_device_flush_entire_buffer()) {
|
||||
screen.flush_display_entire_framebuffer();
|
||||
} else if (device_can_flush_buffers) {
|
||||
// If the device needs a flush we need to let it know that we
|
||||
// modified the front buffer!
|
||||
bounding_flash.translate_by(-screen_rect.location());
|
||||
|
|
|
@ -32,6 +32,7 @@ ErrorOr<void> HardwareScreenBackend::open()
|
|||
return Error::from_syscall(String::formatted("failed to ioctl {}", m_device), errno);
|
||||
|
||||
m_can_device_flush_buffers = (properties.partial_flushing_support != 0);
|
||||
m_can_device_flush_entire_framebuffer = (properties.flushing_support != 0);
|
||||
m_can_set_head_buffer = (properties.doublebuffer_support != 0);
|
||||
return {};
|
||||
}
|
||||
|
@ -209,4 +210,13 @@ ErrorOr<void> HardwareScreenBackend::flush_framebuffer_rects(int buffer_index, S
|
|||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> HardwareScreenBackend::flush_framebuffer()
|
||||
{
|
||||
int rc = fb_flush_head(m_framebuffer_fd);
|
||||
if (rc == -ENOTSUP)
|
||||
m_can_device_flush_entire_framebuffer = false;
|
||||
else
|
||||
return Error::from_syscall("fb_flush_head", rc);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@ public:
|
|||
|
||||
virtual ErrorOr<void> flush_framebuffer_rects(int buffer_index, Span<FBRect const> rects) override;
|
||||
|
||||
virtual ErrorOr<void> flush_framebuffer() override;
|
||||
|
||||
virtual ErrorOr<void> unmap_framebuffer() override;
|
||||
virtual ErrorOr<void> map_framebuffer() override;
|
||||
|
||||
|
|
|
@ -527,7 +527,7 @@ void Screen::queue_flush_display_rect(Gfx::IntRect const& flush_region)
|
|||
|
||||
void Screen::flush_display(int buffer_index)
|
||||
{
|
||||
VERIFY(m_backend->m_can_device_flush_buffers);
|
||||
VERIFY(m_backend->m_can_device_flush_buffers || m_backend->m_can_device_flush_entire_framebuffer);
|
||||
auto& flush_rects = *m_flush_rects;
|
||||
if (flush_rects.pending_flush_rects.is_empty())
|
||||
return;
|
||||
|
@ -542,9 +542,15 @@ void Screen::flush_display(int buffer_index)
|
|||
flush_rect.height *= scale_factor;
|
||||
}
|
||||
|
||||
if (m_backend->m_can_device_flush_entire_framebuffer) {
|
||||
auto return_value = m_backend->flush_framebuffer();
|
||||
if (return_value.is_error())
|
||||
dbgln("Screen #{}: Error flushing display: {}", index(), return_value.error());
|
||||
} else {
|
||||
auto return_value = m_backend->flush_framebuffer_rects(buffer_index, flush_rects.pending_flush_rects.span());
|
||||
if (return_value.is_error())
|
||||
dbgln("Screen #{}: Error flushing display: {}", index(), return_value.error());
|
||||
}
|
||||
|
||||
flush_rects.too_many_pending_flush_rects = false;
|
||||
flush_rects.pending_flush_rects.clear_with_capacity();
|
||||
|
@ -555,6 +561,14 @@ void Screen::write_all_display_contents()
|
|||
MUST(m_backend->write_all_contents(m_virtual_rect));
|
||||
}
|
||||
|
||||
void Screen::flush_display_entire_framebuffer()
|
||||
{
|
||||
VERIFY(m_backend->m_can_device_flush_entire_framebuffer);
|
||||
auto return_value = m_backend->flush_framebuffer();
|
||||
if (return_value.is_error())
|
||||
dbgln("Screen #{}: Error flushing display front buffer: {}", index(), return_value.error());
|
||||
}
|
||||
|
||||
void Screen::flush_display_front_buffer(int front_buffer_index, Gfx::IntRect& rect)
|
||||
{
|
||||
VERIFY(m_backend->m_can_device_flush_buffers);
|
||||
|
|
|
@ -168,9 +168,11 @@ public:
|
|||
Gfx::IntRect rect() const { return m_virtual_rect; }
|
||||
|
||||
bool can_device_flush_buffers() const { return m_backend->m_can_device_flush_buffers; }
|
||||
bool can_device_flush_entire_buffer() const { return m_backend->m_can_device_flush_entire_framebuffer; }
|
||||
void queue_flush_display_rect(Gfx::IntRect const& rect);
|
||||
void flush_display(int buffer_index);
|
||||
void flush_display_front_buffer(int front_buffer_index, Gfx::IntRect&);
|
||||
void flush_display_entire_framebuffer();
|
||||
|
||||
CompositorScreenData& compositor_screen_data() { return *m_compositor_screen_data; }
|
||||
|
||||
|
|
|
@ -31,12 +31,15 @@ public:
|
|||
virtual ErrorOr<void> unmap_framebuffer() = 0;
|
||||
virtual ErrorOr<void> map_framebuffer() = 0;
|
||||
|
||||
virtual ErrorOr<void> flush_framebuffer() = 0;
|
||||
|
||||
virtual ErrorOr<void> set_head_resolution(FBHeadResolution) = 0;
|
||||
virtual ErrorOr<FBHeadProperties> get_head_properties() = 0;
|
||||
|
||||
virtual ErrorOr<void> write_all_contents(Gfx::IntRect const&) { return {}; }
|
||||
|
||||
bool m_can_device_flush_buffers { true };
|
||||
bool m_can_device_flush_entire_framebuffer { true };
|
||||
bool m_can_set_head_buffer { false };
|
||||
|
||||
Gfx::ARGB32* m_framebuffer { nullptr };
|
||||
|
|
|
@ -30,6 +30,8 @@ private:
|
|||
|
||||
virtual ErrorOr<void> flush_framebuffer_rects(int, Span<FBRect const>) override { return {}; }
|
||||
|
||||
virtual ErrorOr<void> flush_framebuffer() override { return {}; }
|
||||
|
||||
virtual ErrorOr<void> unmap_framebuffer() override;
|
||||
virtual ErrorOr<void> map_framebuffer() override;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue