mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 13:27:35 +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);
|
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
|
__END_DECLS
|
||||||
|
|
|
@ -629,7 +629,9 @@ void Compositor::flush(Screen& screen)
|
||||||
bounding_flash = bounding_flash.united(rect);
|
bounding_flash = bounding_flash.united(rect);
|
||||||
}
|
}
|
||||||
if (!bounding_flash.is_empty()) {
|
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
|
// If the device needs a flush we need to let it know that we
|
||||||
// modified the front buffer!
|
// modified the front buffer!
|
||||||
bounding_flash.translate_by(-screen_rect.location());
|
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);
|
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_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);
|
m_can_set_head_buffer = (properties.doublebuffer_support != 0);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -209,4 +210,13 @@ ErrorOr<void> HardwareScreenBackend::flush_framebuffer_rects(int buffer_index, S
|
||||||
return {};
|
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_rects(int buffer_index, Span<FBRect const> rects) override;
|
||||||
|
|
||||||
|
virtual ErrorOr<void> flush_framebuffer() override;
|
||||||
|
|
||||||
virtual ErrorOr<void> unmap_framebuffer() override;
|
virtual ErrorOr<void> unmap_framebuffer() override;
|
||||||
virtual ErrorOr<void> map_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)
|
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;
|
auto& flush_rects = *m_flush_rects;
|
||||||
if (flush_rects.pending_flush_rects.is_empty())
|
if (flush_rects.pending_flush_rects.is_empty())
|
||||||
return;
|
return;
|
||||||
|
@ -542,9 +542,15 @@ void Screen::flush_display(int buffer_index)
|
||||||
flush_rect.height *= scale_factor;
|
flush_rect.height *= scale_factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto return_value = m_backend->flush_framebuffer_rects(buffer_index, flush_rects.pending_flush_rects.span());
|
if (m_backend->m_can_device_flush_entire_framebuffer) {
|
||||||
if (return_value.is_error())
|
auto return_value = m_backend->flush_framebuffer();
|
||||||
dbgln("Screen #{}: Error flushing display: {}", index(), return_value.error());
|
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.too_many_pending_flush_rects = false;
|
||||||
flush_rects.pending_flush_rects.clear_with_capacity();
|
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));
|
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)
|
void Screen::flush_display_front_buffer(int front_buffer_index, Gfx::IntRect& rect)
|
||||||
{
|
{
|
||||||
VERIFY(m_backend->m_can_device_flush_buffers);
|
VERIFY(m_backend->m_can_device_flush_buffers);
|
||||||
|
|
|
@ -168,9 +168,11 @@ public:
|
||||||
Gfx::IntRect rect() const { return m_virtual_rect; }
|
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_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 queue_flush_display_rect(Gfx::IntRect const& rect);
|
||||||
void flush_display(int buffer_index);
|
void flush_display(int buffer_index);
|
||||||
void flush_display_front_buffer(int front_buffer_index, Gfx::IntRect&);
|
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; }
|
CompositorScreenData& compositor_screen_data() { return *m_compositor_screen_data; }
|
||||||
|
|
||||||
|
|
|
@ -31,12 +31,15 @@ public:
|
||||||
virtual ErrorOr<void> unmap_framebuffer() = 0;
|
virtual ErrorOr<void> unmap_framebuffer() = 0;
|
||||||
virtual ErrorOr<void> map_framebuffer() = 0;
|
virtual ErrorOr<void> map_framebuffer() = 0;
|
||||||
|
|
||||||
|
virtual ErrorOr<void> flush_framebuffer() = 0;
|
||||||
|
|
||||||
virtual ErrorOr<void> set_head_resolution(FBHeadResolution) = 0;
|
virtual ErrorOr<void> set_head_resolution(FBHeadResolution) = 0;
|
||||||
virtual ErrorOr<FBHeadProperties> get_head_properties() = 0;
|
virtual ErrorOr<FBHeadProperties> get_head_properties() = 0;
|
||||||
|
|
||||||
virtual ErrorOr<void> write_all_contents(Gfx::IntRect const&) { return {}; }
|
virtual ErrorOr<void> write_all_contents(Gfx::IntRect const&) { return {}; }
|
||||||
|
|
||||||
bool m_can_device_flush_buffers { true };
|
bool m_can_device_flush_buffers { true };
|
||||||
|
bool m_can_device_flush_entire_framebuffer { true };
|
||||||
bool m_can_set_head_buffer { false };
|
bool m_can_set_head_buffer { false };
|
||||||
|
|
||||||
Gfx::ARGB32* m_framebuffer { nullptr };
|
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_rects(int, Span<FBRect const>) override { return {}; }
|
||||||
|
|
||||||
|
virtual ErrorOr<void> flush_framebuffer() override { return {}; }
|
||||||
|
|
||||||
virtual ErrorOr<void> unmap_framebuffer() override;
|
virtual ErrorOr<void> unmap_framebuffer() override;
|
||||||
virtual ErrorOr<void> map_framebuffer() override;
|
virtual ErrorOr<void> map_framebuffer() override;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue