summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom <tomut@yahoo.com>2021-07-10 10:42:04 -0600
committerAndreas Kling <kling@serenityos.org>2021-07-10 21:24:52 +0200
commit02651f8dc608b062bc81ade8d6318b4d78f9a7cd (patch)
treecea7fafe5472f6ee0a14ff1b9b4baff5dca23ee6
parente718de454e71f15e0284ecb2a725cfe3a8960c3b (diff)
downloadserenity-02651f8dc608b062bc81ade8d6318b4d78f9a7cd.zip
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.
-rw-r--r--Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.cpp14
-rw-r--r--Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.h1
2 files changed, 15 insertions, 0 deletions
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: