summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorLiav A <liavalb@gmail.com>2022-04-30 13:55:00 +0300
committerAndreas Kling <kling@serenityos.org>2022-05-05 20:55:57 +0200
commit4ff6150f1b760b0674f32b44bbc58e5c2971ffa4 (patch)
treecfb0cc16d0d4f827d466069de1cc75b1e2464bb6 /Userland
parent41283a2de6f3861eb36648041462b10b7206493e (diff)
downloadserenity-4ff6150f1b760b0674f32b44bbc58e5c2971ffa4.zip
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.
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Services/WindowServer/Compositor.cpp4
-rw-r--r--Userland/Services/WindowServer/HardwareScreenBackend.cpp10
-rw-r--r--Userland/Services/WindowServer/HardwareScreenBackend.h2
-rw-r--r--Userland/Services/WindowServer/Screen.cpp22
-rw-r--r--Userland/Services/WindowServer/Screen.h2
-rw-r--r--Userland/Services/WindowServer/ScreenBackend.h3
-rw-r--r--Userland/Services/WindowServer/VirtualScreenBackend.h2
7 files changed, 40 insertions, 5 deletions
diff --git a/Userland/Services/WindowServer/Compositor.cpp b/Userland/Services/WindowServer/Compositor.cpp
index 6941a5c6ca..7a5243b45b 100644
--- a/Userland/Services/WindowServer/Compositor.cpp
+++ b/Userland/Services/WindowServer/Compositor.cpp
@@ -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());
diff --git a/Userland/Services/WindowServer/HardwareScreenBackend.cpp b/Userland/Services/WindowServer/HardwareScreenBackend.cpp
index f0bf2912b5..4784658ccb 100644
--- a/Userland/Services/WindowServer/HardwareScreenBackend.cpp
+++ b/Userland/Services/WindowServer/HardwareScreenBackend.cpp
@@ -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 {};
+}
}
diff --git a/Userland/Services/WindowServer/HardwareScreenBackend.h b/Userland/Services/WindowServer/HardwareScreenBackend.h
index e1ce874ea2..16e3deeaa9 100644
--- a/Userland/Services/WindowServer/HardwareScreenBackend.h
+++ b/Userland/Services/WindowServer/HardwareScreenBackend.h
@@ -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;
diff --git a/Userland/Services/WindowServer/Screen.cpp b/Userland/Services/WindowServer/Screen.cpp
index ef6b24165a..de3a1e75e3 100644
--- a/Userland/Services/WindowServer/Screen.cpp
+++ b/Userland/Services/WindowServer/Screen.cpp
@@ -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;
}
- 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());
+ 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);
diff --git a/Userland/Services/WindowServer/Screen.h b/Userland/Services/WindowServer/Screen.h
index 8737a92eae..c54b1a274a 100644
--- a/Userland/Services/WindowServer/Screen.h
+++ b/Userland/Services/WindowServer/Screen.h
@@ -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; }
diff --git a/Userland/Services/WindowServer/ScreenBackend.h b/Userland/Services/WindowServer/ScreenBackend.h
index 4e96bd7f2f..efc158e484 100644
--- a/Userland/Services/WindowServer/ScreenBackend.h
+++ b/Userland/Services/WindowServer/ScreenBackend.h
@@ -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 };
diff --git a/Userland/Services/WindowServer/VirtualScreenBackend.h b/Userland/Services/WindowServer/VirtualScreenBackend.h
index 8d59b9cf5a..647acdd327 100644
--- a/Userland/Services/WindowServer/VirtualScreenBackend.h
+++ b/Userland/Services/WindowServer/VirtualScreenBackend.h
@@ -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;