diff options
author | Tom <tomut@yahoo.com> | 2021-06-26 11:04:01 -0600 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-06-27 09:46:27 +0200 |
commit | 38af4c29e69326c5aa7fab82f4870d03bc4f71f6 (patch) | |
tree | 88401a4952482bca628c52f46b5712151b64006a /Kernel | |
parent | 56cd0f929ef19fc19f50d9d45e2e1f43ef8ac755 (diff) | |
download | serenity-38af4c29e69326c5aa7fab82f4870d03bc4f71f6.zip |
WindowServer: Coalesce flushing buffers into one ioctl() call
We regularily need to flush many rectangles, so instead of making many
expensive ioctl() calls to the framebuffer driver, collect the
rectangles and only make one call. And if we have too many rectangles
then it may be cheaper to just update the entire region, in which case
we simply convert them all into a union and just flush that one
rectangle instead.
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/API/FB.h | 7 | ||||
-rw-r--r-- | Kernel/Graphics/FramebufferDevice.cpp | 2 | ||||
-rw-r--r-- | Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.cpp | 30 |
3 files changed, 26 insertions, 13 deletions
diff --git a/Kernel/API/FB.h b/Kernel/API/FB.h index 94b6c07677..25b00e8809 100644 --- a/Kernel/API/FB.h +++ b/Kernel/API/FB.h @@ -38,9 +38,12 @@ ALWAYS_INLINE int fb_set_buffer(int fd, int index) return ioctl(fd, FB_IOCTL_SET_BUFFER, index); } -ALWAYS_INLINE int fb_flush_buffer(int fd, FBRect* rect) +ALWAYS_INLINE int fb_flush_buffers(int fd, FBRect const* rects, unsigned count) { - return ioctl(fd, FB_IOCTL_FLUSH_BUFFER, rect); + FBRects fb_rects; + fb_rects.count = count; + fb_rects.rects = rects; + return ioctl(fd, FB_IOCTL_FLUSH_BUFFERS, &fb_rects); } __END_DECLS diff --git a/Kernel/Graphics/FramebufferDevice.cpp b/Kernel/Graphics/FramebufferDevice.cpp index b66583ff50..c77dd4b2e7 100644 --- a/Kernel/Graphics/FramebufferDevice.cpp +++ b/Kernel/Graphics/FramebufferDevice.cpp @@ -215,6 +215,8 @@ int FramebufferDevice::ioctl(FileDescription&, unsigned request, FlatPtr arg) return -EFAULT; return 0; } + case FB_IOCTL_FLUSH_BUFFERS: + return -ENOTSUP; default: return -EINVAL; }; diff --git a/Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.cpp b/Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.cpp index bbb69810ac..0c55be5887 100644 --- a/Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.cpp +++ b/Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.cpp @@ -147,18 +147,26 @@ int VirtIOFrameBufferDevice::ioctl(FileDescription&, unsigned request, FlatPtr a return -EFAULT; return 0; } - case FB_IOCTL_FLUSH_BUFFER: { - FBRect user_dirty_rect; - if (!copy_from_user(&user_dirty_rect, (FBRect*)arg)) + case FB_IOCTL_FLUSH_BUFFERS: { + FBRects user_dirty_rects; + if (!copy_from_user(&user_dirty_rects, (FBRects*)arg)) return -EFAULT; - VirtIOGPURect dirty_rect { - .x = user_dirty_rect.x, - .y = user_dirty_rect.y, - .width = user_dirty_rect.width, - .height = user_dirty_rect.height - }; - if (m_are_writes_active) - flush_dirty_window(dirty_rect); + if (Checked<unsigned>::multiplication_would_overflow(user_dirty_rects.count, sizeof(FBRect))) + return -EFAULT; + for (unsigned i = 0; i < user_dirty_rects.count; i++) { + FBRect user_dirty_rect; + if (!copy_from_user(&user_dirty_rect, &user_dirty_rects.rects[i])) + return -EFAULT; + if (m_are_writes_active) { + VirtIOGPURect dirty_rect { + .x = user_dirty_rect.x, + .y = user_dirty_rect.y, + .width = user_dirty_rect.width, + .height = user_dirty_rect.height + }; + flush_dirty_window(dirty_rect); + } + } return 0; } default: |