From 02651f8dc608b062bc81ade8d6318b4d78f9a7cd Mon Sep 17 00:00:00 2001 From: Tom Date: Sat, 10 Jul 2021 10:42:04 -0600 Subject: [PATCH] Kernel: Make VirtIO GPU buffer flipping more spec compliant The spec requires a flush after setting the new buffer resource id, which is required by QEMUs SDL backend but not the GTK backend. This brings us in line with the spec and makes it work for the SDL backend. --- .../Graphics/VirtIOGPU/VirtIOFrameBufferDevice.cpp | 14 ++++++++++++++ .../Graphics/VirtIOGPU/VirtIOFrameBufferDevice.h | 1 + 2 files changed, 15 insertions(+) diff --git a/Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.cpp b/Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.cpp index 6e8bbce64d..11dd307d15 100644 --- a/Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.cpp +++ b/Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.cpp @@ -128,6 +128,8 @@ void VirtIOFrameBufferDevice::set_buffer(int buffer_index) return; m_current_buffer = &buffer; m_gpu.set_scanout_resource(m_scanout.value(), buffer.resource_id, display_info().rect); + m_gpu.flush_displayed_image(buffer.dirty_rect, buffer.resource_id); // QEMU SDL backend requires this (as per spec) + buffer.dirty_rect = {}; } int VirtIOFrameBufferDevice::ioctl(FileDescription&, unsigned request, FlatPtr arg) @@ -196,6 +198,18 @@ int VirtIOFrameBufferDevice::ioctl(FileDescription&, unsigned request, FlatPtr a if (&buffer == m_current_buffer) { // Flushing directly to screen flush_displayed_image(dirty_rect, buffer); + buffer.dirty_rect = {}; + } else { + if (buffer.dirty_rect.width == 0 || buffer.dirty_rect.height == 0) { + buffer.dirty_rect = dirty_rect; + } else { + auto current_dirty_right = buffer.dirty_rect.x + buffer.dirty_rect.width; + auto current_dirty_bottom = buffer.dirty_rect.y + buffer.dirty_rect.height; + buffer.dirty_rect.x = min(buffer.dirty_rect.x, dirty_rect.x); + buffer.dirty_rect.y = min(buffer.dirty_rect.y, dirty_rect.y); + buffer.dirty_rect.width = max(current_dirty_right, dirty_rect.x + dirty_rect.width) - buffer.dirty_rect.x; + buffer.dirty_rect.height = max(current_dirty_bottom, dirty_rect.y + dirty_rect.height) - buffer.dirty_rect.y; + } } } } diff --git a/Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.h b/Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.h index 003ce823fd..323feecd93 100644 --- a/Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.h +++ b/Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.h @@ -19,6 +19,7 @@ class VirtIOFrameBufferDevice final : public BlockDevice { size_t framebuffer_offset { 0 }; u8* framebuffer_data { nullptr }; VirtIOGPUResourceID resource_id { 0 }; + VirtIOGPURect dirty_rect {}; }; public: