diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index d9e4319a628..77d7d4d4fc9 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -71,10 +71,10 @@ set(KERNEL_SOURCES Graphics/FramebufferDevice.cpp Graphics/GraphicsManagement.cpp Graphics/Intel/NativeGraphicsAdapter.cpp - Graphics/VirtIOGPU/VirtIOFrameBufferDevice.cpp - Graphics/VirtIOGPU/VirtIOGPUConsole.cpp + Graphics/VirtIOGPU/FrameBufferDevice.cpp + Graphics/VirtIOGPU/Console.cpp Graphics/VirtIOGPU/VirtIOGPU.cpp - Graphics/VirtIOGPU/VirtIOGraphicsAdapter.cpp + Graphics/VirtIOGPU/GraphicsAdapter.cpp Graphics/VGACompatibleAdapter.cpp Storage/Partition/DiskPartition.cpp Storage/Partition/DiskPartitionMetadata.cpp diff --git a/Kernel/Graphics/GraphicsManagement.cpp b/Kernel/Graphics/GraphicsManagement.cpp index f2576c0fc30..9a17ea96b0e 100644 --- a/Kernel/Graphics/GraphicsManagement.cpp +++ b/Kernel/Graphics/GraphicsManagement.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include @@ -91,7 +91,7 @@ UNMAP_AFTER_INIT bool GraphicsManagement::determine_and_initialize_graphics_devi break; case PCI::VendorID::VirtIO: dmesgln("Graphics: Using VirtIO console"); - adapter = Graphics::VirtIOGraphicsAdapter::initialize(address); + adapter = Graphics::VirtIOGPU::GraphicsAdapter::initialize(address); break; default: if (!is_vga_compatible_pci_device(address)) diff --git a/Kernel/Graphics/GraphicsManagement.h b/Kernel/Graphics/GraphicsManagement.h index bb99dcc2c86..8ecc31447f5 100644 --- a/Kernel/Graphics/GraphicsManagement.h +++ b/Kernel/Graphics/GraphicsManagement.h @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include namespace Kernel { @@ -26,7 +26,7 @@ class GraphicsManagement { friend class BochsGraphicsAdapter; friend class IntelNativeGraphicsAdapter; friend class VGACompatibleAdapter; - friend class Graphics::VirtIOGraphicsAdapter; + friend class Graphics::VirtIOGPU::GraphicsAdapter; AK_MAKE_ETERNAL public: diff --git a/Kernel/Graphics/VirtIOGPU/VirtIOGPUConsole.cpp b/Kernel/Graphics/VirtIOGPU/Console.cpp similarity index 73% rename from Kernel/Graphics/VirtIOGPU/VirtIOGPUConsole.cpp rename to Kernel/Graphics/VirtIOGPU/Console.cpp index 7ab490bdcd5..32e9a820234 100644 --- a/Kernel/Graphics/VirtIOGPU/VirtIOGPUConsole.cpp +++ b/Kernel/Graphics/VirtIOGPU/Console.cpp @@ -4,11 +4,11 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include -#include +#include +#include #include -namespace Kernel::Graphics { +namespace Kernel::Graphics::VirtIOGPU { constexpr static AK::Time refresh_interval = AK::Time::from_milliseconds(16); @@ -30,36 +30,36 @@ void DirtyRect::union_rect(size_t x, size_t y, size_t width, size_t height) } } -NonnullRefPtr VirtIOGPUConsole::initialize(RefPtr const& framebuffer_device) +NonnullRefPtr Console::initialize(RefPtr const& framebuffer_device) { - return adopt_ref(*new VirtIOGPUConsole(framebuffer_device)); + return adopt_ref(*new Console(framebuffer_device)); } -VirtIOGPUConsole::VirtIOGPUConsole(RefPtr const& framebuffer_device) +Console::Console(RefPtr const& framebuffer_device) : GenericFramebufferConsole(framebuffer_device->width(), framebuffer_device->height(), framebuffer_device->pitch()) , m_framebuffer_device(framebuffer_device) { enqueue_refresh_timer(); } -void VirtIOGPUConsole::set_resolution(size_t width, size_t height, size_t) +void Console::set_resolution(size_t width, size_t height, size_t) { auto did_set_resolution = m_framebuffer_device->try_to_set_resolution(width, height); VERIFY(did_set_resolution); } -void VirtIOGPUConsole::flush(size_t x, size_t y, size_t width, size_t height) +void Console::flush(size_t x, size_t y, size_t width, size_t height) { m_dirty_rect.union_rect(x, y, width, height); } -void VirtIOGPUConsole::enqueue_refresh_timer() +void Console::enqueue_refresh_timer() { NonnullRefPtr refresh_timer = adopt_ref(*new Timer()); refresh_timer->setup(CLOCK_MONOTONIC, refresh_interval, [this]() { auto rect = m_dirty_rect; if (rect.is_dirty()) { - VirtIOGPURect dirty_rect { + Protocol::Rect dirty_rect { .x = (u32)rect.x(), .y = (u32)rect.y(), .width = (u32)rect.width(), @@ -75,7 +75,7 @@ void VirtIOGPUConsole::enqueue_refresh_timer() TimerQueue::the().add_timer(move(refresh_timer)); } -void VirtIOGPUConsole::enable() +void Console::enable() { GenericFramebufferConsole::enable(); m_width = m_framebuffer_device->width(); @@ -84,7 +84,7 @@ void VirtIOGPUConsole::enable() m_dirty_rect.union_rect(0, 0, m_width, m_height); } -u8* VirtIOGPUConsole::framebuffer_data() +u8* Console::framebuffer_data() { return m_framebuffer_device->framebuffer_data(); } diff --git a/Kernel/Graphics/VirtIOGPU/VirtIOGPUConsole.h b/Kernel/Graphics/VirtIOGPU/Console.h similarity index 78% rename from Kernel/Graphics/VirtIOGPU/VirtIOGPUConsole.h rename to Kernel/Graphics/VirtIOGPU/Console.h index 5385ab2a91a..9d4911f6b40 100644 --- a/Kernel/Graphics/VirtIOGPU/VirtIOGPUConsole.h +++ b/Kernel/Graphics/VirtIOGPU/Console.h @@ -10,7 +10,7 @@ #include #include -namespace Kernel::Graphics { +namespace Kernel::Graphics::VirtIOGPU { class DirtyRect { public: @@ -30,9 +30,9 @@ private: size_t m_y1 { 0 }; }; -class VirtIOGPUConsole final : public GenericFramebufferConsole { +class Console final : public GenericFramebufferConsole { public: - static NonnullRefPtr initialize(RefPtr const&); + static NonnullRefPtr initialize(RefPtr const&); virtual void set_resolution(size_t width, size_t height, size_t pitch) override; virtual void flush(size_t x, size_t y, size_t width, size_t height) override; @@ -42,8 +42,8 @@ private: void enqueue_refresh_timer(); virtual u8* framebuffer_data() override; - VirtIOGPUConsole(RefPtr const&); - RefPtr m_framebuffer_device; + Console(RefPtr const&); + RefPtr m_framebuffer_device; DirtyRect m_dirty_rect; }; diff --git a/Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.cpp b/Kernel/Graphics/VirtIOGPU/FrameBufferDevice.cpp similarity index 88% rename from Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.cpp rename to Kernel/Graphics/VirtIOGPU/FrameBufferDevice.cpp index 1f0bd9742df..5f1d6941f49 100644 --- a/Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.cpp +++ b/Kernel/Graphics/VirtIOGPU/FrameBufferDevice.cpp @@ -5,12 +5,12 @@ */ #include -#include +#include #include -namespace Kernel::Graphics { +namespace Kernel::Graphics::VirtIOGPU { -VirtIOFrameBufferDevice::VirtIOFrameBufferDevice(VirtIOGPU& virtio_gpu, VirtIOGPUScanoutID scanout) +FrameBufferDevice::FrameBufferDevice(GPU& virtio_gpu, ScanoutID scanout) : BlockDevice(29, GraphicsManagement::the().allocate_minor_device_number()) , m_gpu(virtio_gpu) , m_scanout(scanout) @@ -19,11 +19,11 @@ VirtIOFrameBufferDevice::VirtIOFrameBufferDevice(VirtIOGPU& virtio_gpu, VirtIOGP create_framebuffer(); } -VirtIOFrameBufferDevice::~VirtIOFrameBufferDevice() +FrameBufferDevice::~FrameBufferDevice() { } -void VirtIOFrameBufferDevice::create_framebuffer() +void FrameBufferDevice::create_framebuffer() { // First delete any existing framebuffers to free the memory first m_framebuffer = nullptr; @@ -48,7 +48,7 @@ void VirtIOFrameBufferDevice::create_framebuffer() create_buffer(m_back_buffer, m_buffer_size, m_buffer_size); } -void VirtIOFrameBufferDevice::create_buffer(Buffer& buffer, size_t framebuffer_offset, size_t framebuffer_size) +void FrameBufferDevice::create_buffer(Buffer& buffer, size_t framebuffer_offset, size_t framebuffer_size) { buffer.framebuffer_offset = framebuffer_offset; buffer.framebuffer_data = m_framebuffer->vaddr().as_ptr() + framebuffer_offset; @@ -76,32 +76,32 @@ void VirtIOFrameBufferDevice::create_buffer(Buffer& buffer, size_t framebuffer_o info.enabled = 1; } -VirtIOGPURespDisplayInfo::VirtIOGPUDisplayOne const& VirtIOFrameBufferDevice::display_info() const +Protocol::DisplayInfoResponse::Display const& FrameBufferDevice::display_info() const { return m_gpu.display_info(m_scanout); } -VirtIOGPURespDisplayInfo::VirtIOGPUDisplayOne& VirtIOFrameBufferDevice::display_info() +Protocol::DisplayInfoResponse::Display& FrameBufferDevice::display_info() { return m_gpu.display_info(m_scanout); } -void VirtIOFrameBufferDevice::transfer_framebuffer_data_to_host(VirtIOGPURect const& rect, Buffer& buffer) +void FrameBufferDevice::transfer_framebuffer_data_to_host(Protocol::Rect const& rect, Buffer& buffer) { m_gpu.transfer_framebuffer_data_to_host(m_scanout, rect, buffer.resource_id); } -void VirtIOFrameBufferDevice::flush_dirty_window(VirtIOGPURect const& dirty_rect, Buffer& buffer) +void FrameBufferDevice::flush_dirty_window(Protocol::Rect const& dirty_rect, Buffer& buffer) { m_gpu.flush_dirty_window(m_scanout, dirty_rect, buffer.resource_id); } -void VirtIOFrameBufferDevice::flush_displayed_image(VirtIOGPURect const& dirty_rect, Buffer& buffer) +void FrameBufferDevice::flush_displayed_image(Protocol::Rect const& dirty_rect, Buffer& buffer) { m_gpu.flush_displayed_image(dirty_rect, buffer.resource_id); } -bool VirtIOFrameBufferDevice::try_to_set_resolution(size_t width, size_t height) +bool FrameBufferDevice::try_to_set_resolution(size_t width, size_t height) { if (width > MAX_VIRTIOGPU_RESOLUTION_WIDTH || height > MAX_VIRTIOGPU_RESOLUTION_HEIGHT) return false; @@ -120,7 +120,7 @@ bool VirtIOFrameBufferDevice::try_to_set_resolution(size_t width, size_t height) return true; } -void VirtIOFrameBufferDevice::set_buffer(int buffer_index) +void FrameBufferDevice::set_buffer(int buffer_index) { auto& buffer = buffer_index == 0 ? m_main_buffer : m_back_buffer; MutexLocker locker(m_gpu.operation_lock()); @@ -132,7 +132,7 @@ void VirtIOFrameBufferDevice::set_buffer(int buffer_index) buffer.dirty_rect = {}; } -int VirtIOFrameBufferDevice::ioctl(FileDescription&, unsigned request, FlatPtr arg) +int FrameBufferDevice::ioctl(FileDescription&, unsigned request, FlatPtr arg) { REQUIRE_PROMISE(video); switch (request) { @@ -188,7 +188,7 @@ int VirtIOFrameBufferDevice::ioctl(FileDescription&, unsigned request, FlatPtr a FBRect user_dirty_rect; if (!copy_from_user(&user_dirty_rect, &user_flush_rects.rects[i])) return -EFAULT; - VirtIOGPURect dirty_rect { + Protocol::Rect dirty_rect { .x = user_dirty_rect.x, .y = user_dirty_rect.y, .width = user_dirty_rect.width, @@ -231,7 +231,7 @@ int VirtIOFrameBufferDevice::ioctl(FileDescription&, unsigned request, FlatPtr a }; } -KResultOr VirtIOFrameBufferDevice::mmap(Process& process, FileDescription&, const Range& range, u64 offset, int prot, bool shared) +KResultOr FrameBufferDevice::mmap(Process& process, FileDescription&, const Range& range, u64 offset, int prot, bool shared) { REQUIRE_PROMISE(video); if (!shared) @@ -262,7 +262,7 @@ KResultOr VirtIOFrameBufferDevice::mmap(Process& process, FileDescripti return result; } -void VirtIOFrameBufferDevice::deactivate_writes() +void FrameBufferDevice::deactivate_writes() { m_are_writes_active = false; if (m_userspace_mmap_region) { @@ -276,7 +276,7 @@ void VirtIOFrameBufferDevice::deactivate_writes() clear_to_black(buffer_from_index(0)); } -void VirtIOFrameBufferDevice::activate_writes() +void FrameBufferDevice::activate_writes() { m_are_writes_active = true; auto last_set_buffer_index = m_last_set_buffer_index.load(); @@ -288,7 +288,7 @@ void VirtIOFrameBufferDevice::activate_writes() set_buffer(last_set_buffer_index); } -void VirtIOFrameBufferDevice::clear_to_black(Buffer& buffer) +void FrameBufferDevice::clear_to_black(Buffer& buffer) { auto& info = display_info(); size_t width = info.rect.width; @@ -302,7 +302,7 @@ void VirtIOFrameBufferDevice::clear_to_black(Buffer& buffer) } } -void VirtIOFrameBufferDevice::draw_ntsc_test_pattern(Buffer& buffer) +void FrameBufferDevice::draw_ntsc_test_pattern(Buffer& buffer) { static constexpr u8 colors[12][4] = { { 0xff, 0xff, 0xff, 0xff }, // White @@ -359,7 +359,7 @@ void VirtIOFrameBufferDevice::draw_ntsc_test_pattern(Buffer& buffer) dbgln_if(VIRTIO_DEBUG, "Finish drawing the pattern"); } -u8* VirtIOFrameBufferDevice::framebuffer_data() +u8* FrameBufferDevice::framebuffer_data() { return m_current_buffer->framebuffer_data; } diff --git a/Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.h b/Kernel/Graphics/VirtIOGPU/FrameBufferDevice.h similarity index 80% rename from Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.h rename to Kernel/Graphics/VirtIOGPU/FrameBufferDevice.h index 6955d51d0d6..22815b1dffb 100644 --- a/Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.h +++ b/Kernel/Graphics/VirtIOGPU/FrameBufferDevice.h @@ -11,20 +11,20 @@ #include #include -namespace Kernel::Graphics { +namespace Kernel::Graphics::VirtIOGPU { -class VirtIOFrameBufferDevice final : public BlockDevice { - friend class VirtIOGPUConsole; +class FrameBufferDevice final : public BlockDevice { + friend class Console; struct Buffer { size_t framebuffer_offset { 0 }; u8* framebuffer_data { nullptr }; - VirtIOGPUResourceID resource_id { 0 }; - VirtIOGPURect dirty_rect {}; + Protocol::Rect dirty_rect {}; + ResourceID resource_id { 0 }; }; public: - VirtIOFrameBufferDevice(VirtIOGPU& virtio_gpu, VirtIOGPUScanoutID); - virtual ~VirtIOFrameBufferDevice() override; + FrameBufferDevice(VirtIOGPU::GPU& virtio_gpu, ScanoutID); + virtual ~FrameBufferDevice() override; virtual void deactivate_writes(); virtual void activate_writes(); @@ -42,9 +42,9 @@ public: return page_round_up(sizeof(u32) * width * height); } - void flush_dirty_window(VirtIOGPURect const&, Buffer&); - void transfer_framebuffer_data_to_host(VirtIOGPURect const&, Buffer&); - void flush_displayed_image(VirtIOGPURect const&, Buffer&); + void flush_dirty_window(Protocol::Rect const&, Buffer&); + void transfer_framebuffer_data_to_host(Protocol::Rect const&, Buffer&); + void flush_displayed_image(Protocol::Rect const&, Buffer&); void draw_ntsc_test_pattern(Buffer&); @@ -53,8 +53,8 @@ public: private: virtual StringView class_name() const override { return "VirtIOFrameBuffer"; } - VirtIOGPURespDisplayInfo::VirtIOGPUDisplayOne const& display_info() const; - VirtIOGPURespDisplayInfo::VirtIOGPUDisplayOne& display_info(); + Protocol::DisplayInfoResponse::Display const& display_info() const; + Protocol::DisplayInfoResponse::Display& display_info(); void create_framebuffer(); void create_buffer(Buffer&, size_t, size_t); @@ -82,8 +82,8 @@ private: } Buffer& current_buffer() const { return *m_current_buffer; } - VirtIOGPU& m_gpu; - const VirtIOGPUScanoutID m_scanout; + GPU& m_gpu; + const ScanoutID m_scanout; Buffer* m_current_buffer { nullptr }; Atomic m_last_set_buffer_index { 0 }; Buffer m_main_buffer; diff --git a/Kernel/Graphics/VirtIOGPU/VirtIOGraphicsAdapter.cpp b/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp similarity index 59% rename from Kernel/Graphics/VirtIOGPU/VirtIOGraphicsAdapter.cpp rename to Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp index 7f1e75758b2..53471b564d8 100644 --- a/Kernel/Graphics/VirtIOGPU/VirtIOGraphicsAdapter.cpp +++ b/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp @@ -8,25 +8,25 @@ #include #include #include -#include +#include -namespace Kernel::Graphics { +namespace Kernel::Graphics::VirtIOGPU { -NonnullRefPtr VirtIOGraphicsAdapter::initialize(PCI::Address base_address) +NonnullRefPtr GraphicsAdapter::initialize(PCI::Address base_address) { VERIFY(PCI::get_id(base_address).vendor_id == PCI::VendorID::VirtIO); - return adopt_ref(*new VirtIOGraphicsAdapter(base_address)); + return adopt_ref(*new GraphicsAdapter(base_address)); } -VirtIOGraphicsAdapter::VirtIOGraphicsAdapter(PCI::Address base_address) +GraphicsAdapter::GraphicsAdapter(PCI::Address base_address) : PCI::DeviceController(base_address) { - m_gpu_device = adopt_ref(*new VirtIOGPU(base_address)).leak_ref(); + m_gpu_device = adopt_ref(*new GPU(base_address)).leak_ref(); } -void VirtIOGraphicsAdapter::initialize_framebuffer_devices() +void GraphicsAdapter::initialize_framebuffer_devices() { - dbgln_if(VIRTIO_DEBUG, "VirtIOGPU: Initializing framebuffer devices"); + dbgln_if(VIRTIO_DEBUG, "GPU: Initializing framebuffer devices"); VERIFY(!m_created_framebuffer_devices); m_gpu_device->create_framebuffer_devices(); m_created_framebuffer_devices = true; @@ -35,9 +35,9 @@ void VirtIOGraphicsAdapter::initialize_framebuffer_devices() GraphicsManagement::the().m_console = m_gpu_device->default_console(); } -void VirtIOGraphicsAdapter::enable_consoles() +void GraphicsAdapter::enable_consoles() { - dbgln_if(VIRTIO_DEBUG, "VirtIOGPU: Enabling consoles"); + dbgln_if(VIRTIO_DEBUG, "GPU: Enabling consoles"); m_gpu_device->for_each_framebuffer([&](auto& framebuffer, auto& console) { framebuffer.deactivate_writes(); console.enable(); @@ -45,9 +45,9 @@ void VirtIOGraphicsAdapter::enable_consoles() }); } -void VirtIOGraphicsAdapter::disable_consoles() +void GraphicsAdapter::disable_consoles() { - dbgln_if(VIRTIO_DEBUG, "VirtIOGPU: Disabling consoles"); + dbgln_if(VIRTIO_DEBUG, "GPU: Disabling consoles"); m_gpu_device->for_each_framebuffer([&](auto& framebuffer, auto& console) { console.disable(); framebuffer.activate_writes(); diff --git a/Kernel/Graphics/VirtIOGPU/VirtIOGraphicsAdapter.h b/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h similarity index 73% rename from Kernel/Graphics/VirtIOGPU/VirtIOGraphicsAdapter.h rename to Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h index 132e07e44ea..8a49f86f4fe 100644 --- a/Kernel/Graphics/VirtIOGPU/VirtIOGraphicsAdapter.h +++ b/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h @@ -6,24 +6,24 @@ #pragma once -#include +#include +#include #include -#include -namespace Kernel::Graphics { +namespace Kernel::Graphics::VirtIOGPU { -class VirtIOGraphicsAdapter final +class GraphicsAdapter final : public GraphicsDevice , public PCI::DeviceController { AK_MAKE_ETERNAL public: - static NonnullRefPtr initialize(PCI::Address); + static NonnullRefPtr initialize(PCI::Address); virtual bool framebuffer_devices_initialized() const override { return m_created_framebuffer_devices; } private: - explicit VirtIOGraphicsAdapter(PCI::Address base_address); + explicit GraphicsAdapter(PCI::Address base_address); virtual void initialize_framebuffer_devices() override; virtual Type type() const override { return Type::Raw; } @@ -37,7 +37,7 @@ private: virtual bool try_to_set_resolution(size_t, size_t, size_t) override { return false; } virtual bool set_y_offset(size_t, size_t) override { return false; } - RefPtr m_gpu_device; + RefPtr m_gpu_device; bool m_created_framebuffer_devices { false }; }; diff --git a/Kernel/Graphics/VirtIOGPU/Protocol.h b/Kernel/Graphics/VirtIOGPU/Protocol.h new file mode 100644 index 00000000000..8de89a7547e --- /dev/null +++ b/Kernel/Graphics/VirtIOGPU/Protocol.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2021, Sahan Fernando + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#define VIRTIO_GPU_MAX_SCANOUTS 16 + +namespace Kernel::Graphics::VirtIOGPU::Protocol { + +// Specification equivalent: enum virtio_gpu_ctrl_type +enum class CommandType : u32 { + /* 2d commands */ + VIRTIO_GPU_CMD_GET_DISPLAY_INFO = 0x0100, + VIRTIO_GPU_CMD_RESOURCE_CREATE_2D, + VIRTIO_GPU_CMD_RESOURCE_UNREF, + VIRTIO_GPU_CMD_SET_SCANOUT, + VIRTIO_GPU_CMD_RESOURCE_FLUSH, + VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D, + VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING, + VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING, + VIRTIO_GPU_CMD_GET_CAPSET_INFO, + VIRTIO_GPU_CMD_GET_CAPSET, + VIRTIO_GPU_CMD_GET_EDID, + + /* cursor commands */ + VIRTIO_GPU_CMD_UPDATE_CURSOR = 0x0300, + VIRTIO_GPU_CMD_MOVE_CURSOR, + + /* success responses */ + VIRTIO_GPU_RESP_OK_NODATA = 0x1100, + VIRTIO_GPU_RESP_OK_DISPLAY_INFO, + VIRTIO_GPU_RESP_OK_CAPSET_INFO, + VIRTIO_GPU_RESP_OK_CAPSET, + VIRTIO_GPU_RESP_OK_EDID, + + /* error responses */ + VIRTIO_GPU_RESP_ERR_UNSPEC = 0x1200, + VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY, + VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID, + VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID, + VIRTIO_GPU_RESP_ERR_INVALID_CONTEXT_ID, + VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER, +}; + +// Specification equivalent: struct virtio_gpu_ctrl_hdr +struct ControlHeader { + u32 type; + u32 flags; + u64 fence_id; + u32 context_id; + u32 padding; +}; + +// Specification equivalent: struct virtio_gpu_rect +struct Rect { + u32 x; + u32 y; + u32 width; + u32 height; +}; + +// Specification equivalent: struct virtio_gpu_resp_display_info +struct DisplayInfoResponse { + ControlHeader header; + // Specification equivalent: struct virtio_gpu_display_one + struct Display { + Rect rect; + u32 enabled; + u32 flags; + } scanout_modes[VIRTIO_GPU_MAX_SCANOUTS]; +}; + +// Specification equivalent: enum virtio_gpu_formats +enum class TextureFormat : u32 { + VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM = 1, + VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM = 2, + VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM = 3, + VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM = 4, + + VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM = 67, + VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM = 68, + + VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM = 121, + VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM = 134, +}; + +// Specification equivalent: struct virtio_gpu_resource_create_2d +struct ResourceCreate2D { + ControlHeader header; + u32 resource_id; + u32 format; + u32 width; + u32 height; +}; + +// Specification equivalent: struct virtio_gpu_resource_unref +struct ResourceUnref { + ControlHeader header; + u32 resource_id; + u32 padding; +}; + +// Specification equivalent: struct virtio_gpu_set_scanout +struct SetScanOut { + ControlHeader header; + Rect rect; + u32 scanout_id; + u32 resource_id; +}; + +// Specification equivalent: struct virtio_gpu_mem_entry +struct MemoryEntry { + u64 address; + u32 length; + u32 padding; +}; + +// Specification equivalent: struct virtio_gpu_resource_attach_backing +struct ResourceAttachBacking { + ControlHeader header; + u32 resource_id; + u32 num_entries; + MemoryEntry entries[]; +}; + +// Specification equivalent: struct virtio_gpu_resource_detach_backing +struct ResourceDetachBacking { + ControlHeader header; + u32 resource_id; + u32 padding; +}; + +// Specification equivalent: struct virtio_gpu_transfer_to_host_2d +struct TransferToHost2D { + ControlHeader header; + Rect rect; + u64 offset; + u32 resource_id; + u32 padding; +}; + +// Specification equivalent: struct virtio_gpu_resource_flush +struct ResourceFlush { + ControlHeader header; + Rect rect; + u32 resource_id; + u32 padding; +}; + +} diff --git a/Kernel/Graphics/VirtIOGPU/VirtIOGPU.cpp b/Kernel/Graphics/VirtIOGPU/VirtIOGPU.cpp index 1d7acafd3ce..52e159c9ea2 100644 --- a/Kernel/Graphics/VirtIOGPU/VirtIOGPU.cpp +++ b/Kernel/Graphics/VirtIOGPU/VirtIOGPU.cpp @@ -4,18 +4,18 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include -#include +#include #define DEVICE_EVENTS_READ 0x0 #define DEVICE_EVENTS_CLEAR 0x4 #define DEVICE_NUM_SCANOUTS 0x8 -namespace Kernel::Graphics { +namespace Kernel::Graphics::VirtIOGPU { -VirtIOGPU::VirtIOGPU(PCI::Address address) - : VirtIODevice(address, "VirtIOGPU") +GPU::GPU(PCI::Address address) + : VirtIODevice(address, "GPU") , m_scratch_space(MM.allocate_contiguous_kernel_region(32 * PAGE_SIZE, "VirtGPU Scratch Space", Region::Access::Read | Region::Access::Write)) { VERIFY(!!m_scratch_space); @@ -24,16 +24,16 @@ VirtIOGPU::VirtIOGPU(PCI::Address address) bool success = negotiate_features([&](u64 supported_features) { u64 negotiated = 0; if (is_feature_set(supported_features, VIRTIO_GPU_F_VIRGL)) - dbgln_if(VIRTIO_DEBUG, "VirtIOGPU: VIRGL is not yet supported!"); + dbgln_if(VIRTIO_DEBUG, "GPU: VIRGL is not yet supported!"); if (is_feature_set(supported_features, VIRTIO_GPU_F_EDID)) - dbgln_if(VIRTIO_DEBUG, "VirtIOGPU: EDID is not yet supported!"); + dbgln_if(VIRTIO_DEBUG, "GPU: EDID is not yet supported!"); return negotiated; }); if (success) { read_config_atomic([&]() { m_num_scanouts = config_read32(*cfg, DEVICE_NUM_SCANOUTS); }); - dbgln_if(VIRTIO_DEBUG, "VirtIOGPU: num_scanouts: {}", m_num_scanouts); + dbgln_if(VIRTIO_DEBUG, "GPU: num_scanouts: {}", m_num_scanouts); success = setup_queues(2); // CONTROLQ + CURSORQ } VERIFY(success); @@ -46,27 +46,27 @@ VirtIOGPU::VirtIOGPU(PCI::Address address) } } -VirtIOGPU::~VirtIOGPU() +GPU::~GPU() { } -void VirtIOGPU::create_framebuffer_devices() +void GPU::create_framebuffer_devices() { for (size_t i = 0; i < min(m_num_scanouts, VIRTIO_GPU_MAX_SCANOUTS); i++) { auto& scanout = m_scanouts[i]; - scanout.framebuffer = adopt_ref(*new VirtIOFrameBufferDevice(*this, i)); - scanout.console = Kernel::Graphics::VirtIOGPUConsole::initialize(scanout.framebuffer); + scanout.framebuffer = adopt_ref(*new VirtIOGPU::FrameBufferDevice(*this, i)); + scanout.console = Kernel::Graphics::VirtIOGPU::Console::initialize(scanout.framebuffer); } } -bool VirtIOGPU::handle_device_config_change() +bool GPU::handle_device_config_change() { return false; } -void VirtIOGPU::handle_queue_update(u16 queue_index) +void GPU::handle_queue_update(u16 queue_index) { - dbgln_if(VIRTIO_DEBUG, "VirtIOGPU: Handle queue update"); + dbgln_if(VIRTIO_DEBUG, "GPU: Handle queue update"); VERIFY(queue_index == CONTROLQ); auto& queue = get_queue(CONTROLQ); @@ -75,23 +75,23 @@ void VirtIOGPU::handle_queue_update(u16 queue_index) m_outstanding_request.wake_all(); } -u32 VirtIOGPU::get_pending_events() +u32 GPU::get_pending_events() { return config_read32(*m_device_configuration, DEVICE_EVENTS_READ); } -void VirtIOGPU::clear_pending_events(u32 event_bitmask) +void GPU::clear_pending_events(u32 event_bitmask) { config_write32(*m_device_configuration, DEVICE_EVENTS_CLEAR, event_bitmask); } -void VirtIOGPU::query_display_information() +void GPU::query_display_information() { VERIFY(m_operation_lock.is_locked()); - auto& request = *reinterpret_cast(m_scratch_space->vaddr().as_ptr()); - auto& response = *reinterpret_cast((m_scratch_space->vaddr().offset(sizeof(request)).as_ptr())); + auto& request = *reinterpret_cast(m_scratch_space->vaddr().as_ptr()); + auto& response = *reinterpret_cast((m_scratch_space->vaddr().offset(sizeof(request)).as_ptr())); - populate_virtio_gpu_request_header(request, VirtIOGPUCtrlType::VIRTIO_GPU_CMD_GET_DISPLAY_INFO, VIRTIO_GPU_FLAG_FENCE); + populate_virtio_gpu_request_header(request, Protocol::CommandType::VIRTIO_GPU_CMD_GET_DISPLAY_INFO, VIRTIO_GPU_FLAG_FENCE); synchronous_virtio_gpu_command(start_of_scratch_space(), sizeof(request), sizeof(response)); @@ -105,28 +105,28 @@ void VirtIOGPU::query_display_information() VERIFY(m_default_scanout.has_value()); } -VirtIOGPUResourceID VirtIOGPU::create_2d_resource(VirtIOGPURect rect) +ResourceID GPU::create_2d_resource(Protocol::Rect rect) { VERIFY(m_operation_lock.is_locked()); - auto& request = *reinterpret_cast(m_scratch_space->vaddr().as_ptr()); - auto& response = *reinterpret_cast((m_scratch_space->vaddr().offset(sizeof(request)).as_ptr())); + auto& request = *reinterpret_cast(m_scratch_space->vaddr().as_ptr()); + auto& response = *reinterpret_cast((m_scratch_space->vaddr().offset(sizeof(request)).as_ptr())); - populate_virtio_gpu_request_header(request.header, VirtIOGPUCtrlType::VIRTIO_GPU_CMD_RESOURCE_CREATE_2D, VIRTIO_GPU_FLAG_FENCE); + populate_virtio_gpu_request_header(request.header, Protocol::CommandType::VIRTIO_GPU_CMD_RESOURCE_CREATE_2D, VIRTIO_GPU_FLAG_FENCE); auto resource_id = allocate_resource_id(); request.resource_id = resource_id.value(); request.width = rect.width; request.height = rect.height; - request.format = static_cast(VirtIOGPUFormats::VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM); + request.format = static_cast(Protocol::TextureFormat::VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM); synchronous_virtio_gpu_command(start_of_scratch_space(), sizeof(request), sizeof(response)); - VERIFY(response.type == static_cast(VirtIOGPUCtrlType::VIRTIO_GPU_RESP_OK_NODATA)); - dbgln_if(VIRTIO_DEBUG, "VirtIOGPU: Allocated 2d resource with id {}", resource_id.value()); + VERIFY(response.type == static_cast(Protocol::CommandType::VIRTIO_GPU_RESP_OK_NODATA)); + dbgln_if(VIRTIO_DEBUG, "GPU: Allocated 2d resource with id {}", resource_id.value()); return resource_id; } -void VirtIOGPU::ensure_backing_storage(Region const& region, size_t buffer_offset, size_t buffer_length, VirtIOGPUResourceID resource_id) +void GPU::ensure_backing_storage(Region const& region, size_t buffer_offset, size_t buffer_length, ResourceID resource_id) { VERIFY(m_operation_lock.is_locked()); @@ -136,11 +136,11 @@ void VirtIOGPU::ensure_backing_storage(Region const& region, size_t buffer_offse size_t num_mem_regions = buffer_length / PAGE_SIZE; // Send request - auto& request = *reinterpret_cast(m_scratch_space->vaddr().as_ptr()); - const size_t header_block_size = sizeof(request) + num_mem_regions * sizeof(VirtIOGPUMemEntry); - auto& response = *reinterpret_cast((m_scratch_space->vaddr().offset(header_block_size).as_ptr())); + auto& request = *reinterpret_cast(m_scratch_space->vaddr().as_ptr()); + const size_t header_block_size = sizeof(request) + num_mem_regions * sizeof(Protocol::MemoryEntry); + auto& response = *reinterpret_cast((m_scratch_space->vaddr().offset(header_block_size).as_ptr())); - populate_virtio_gpu_request_header(request.header, VirtIOGPUCtrlType::VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING, VIRTIO_GPU_FLAG_FENCE); + populate_virtio_gpu_request_header(request.header, Protocol::CommandType::VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING, VIRTIO_GPU_FLAG_FENCE); request.resource_id = resource_id.value(); request.num_entries = num_mem_regions; for (size_t i = 0; i < num_mem_regions; ++i) { @@ -150,74 +150,74 @@ void VirtIOGPU::ensure_backing_storage(Region const& region, size_t buffer_offse synchronous_virtio_gpu_command(start_of_scratch_space(), header_block_size, sizeof(response)); - VERIFY(response.type == static_cast(VirtIOGPUCtrlType::VIRTIO_GPU_RESP_OK_NODATA)); - dbgln_if(VIRTIO_DEBUG, "VirtIOGPU: Allocated backing storage"); + VERIFY(response.type == static_cast(Protocol::CommandType::VIRTIO_GPU_RESP_OK_NODATA)); + dbgln_if(VIRTIO_DEBUG, "GPU: Allocated backing storage"); } -void VirtIOGPU::detach_backing_storage(VirtIOGPUResourceID resource_id) +void GPU::detach_backing_storage(ResourceID resource_id) { VERIFY(m_operation_lock.is_locked()); - auto& request = *reinterpret_cast(m_scratch_space->vaddr().as_ptr()); - auto& response = *reinterpret_cast((m_scratch_space->vaddr().offset(sizeof(request)).as_ptr())); + auto& request = *reinterpret_cast(m_scratch_space->vaddr().as_ptr()); + auto& response = *reinterpret_cast((m_scratch_space->vaddr().offset(sizeof(request)).as_ptr())); - populate_virtio_gpu_request_header(request.header, VirtIOGPUCtrlType::VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING, VIRTIO_GPU_FLAG_FENCE); + populate_virtio_gpu_request_header(request.header, Protocol::CommandType::VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING, VIRTIO_GPU_FLAG_FENCE); request.resource_id = resource_id.value(); synchronous_virtio_gpu_command(start_of_scratch_space(), sizeof(request), sizeof(response)); - VERIFY(response.type == static_cast(VirtIOGPUCtrlType::VIRTIO_GPU_RESP_OK_NODATA)); - dbgln_if(VIRTIO_DEBUG, "VirtIOGPU: Detached backing storage"); + VERIFY(response.type == static_cast(Protocol::CommandType::VIRTIO_GPU_RESP_OK_NODATA)); + dbgln_if(VIRTIO_DEBUG, "GPU: Detached backing storage"); } -void VirtIOGPU::set_scanout_resource(VirtIOGPUScanoutID scanout, VirtIOGPUResourceID resource_id, VirtIOGPURect rect) +void GPU::set_scanout_resource(ScanoutID scanout, ResourceID resource_id, Protocol::Rect rect) { VERIFY(m_operation_lock.is_locked()); - auto& request = *reinterpret_cast(m_scratch_space->vaddr().as_ptr()); - auto& response = *reinterpret_cast((m_scratch_space->vaddr().offset(sizeof(request)).as_ptr())); + auto& request = *reinterpret_cast(m_scratch_space->vaddr().as_ptr()); + auto& response = *reinterpret_cast((m_scratch_space->vaddr().offset(sizeof(request)).as_ptr())); - populate_virtio_gpu_request_header(request.header, VirtIOGPUCtrlType::VIRTIO_GPU_CMD_SET_SCANOUT, VIRTIO_GPU_FLAG_FENCE); + populate_virtio_gpu_request_header(request.header, Protocol::CommandType::VIRTIO_GPU_CMD_SET_SCANOUT, VIRTIO_GPU_FLAG_FENCE); request.resource_id = resource_id.value(); request.scanout_id = scanout.value(); request.rect = rect; synchronous_virtio_gpu_command(start_of_scratch_space(), sizeof(request), sizeof(response)); - VERIFY(response.type == static_cast(VirtIOGPUCtrlType::VIRTIO_GPU_RESP_OK_NODATA)); - dbgln_if(VIRTIO_DEBUG, "VirtIOGPU: Set backing scanout"); + VERIFY(response.type == static_cast(Protocol::CommandType::VIRTIO_GPU_RESP_OK_NODATA)); + dbgln_if(VIRTIO_DEBUG, "GPU: Set backing scanout"); } -void VirtIOGPU::transfer_framebuffer_data_to_host(VirtIOGPUScanoutID scanout, VirtIOGPURect const& dirty_rect, VirtIOGPUResourceID resource_id) +void GPU::transfer_framebuffer_data_to_host(ScanoutID scanout, Protocol::Rect const& dirty_rect, ResourceID resource_id) { VERIFY(m_operation_lock.is_locked()); - auto& request = *reinterpret_cast(m_scratch_space->vaddr().as_ptr()); - auto& response = *reinterpret_cast((m_scratch_space->vaddr().offset(sizeof(request)).as_ptr())); + auto& request = *reinterpret_cast(m_scratch_space->vaddr().as_ptr()); + auto& response = *reinterpret_cast((m_scratch_space->vaddr().offset(sizeof(request)).as_ptr())); - populate_virtio_gpu_request_header(request.header, VirtIOGPUCtrlType::VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D, VIRTIO_GPU_FLAG_FENCE); + populate_virtio_gpu_request_header(request.header, Protocol::CommandType::VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D, VIRTIO_GPU_FLAG_FENCE); request.offset = (dirty_rect.x + (dirty_rect.y * m_scanouts[scanout.value()].display_info.rect.width)) * sizeof(u32); request.resource_id = resource_id.value(); request.rect = dirty_rect; synchronous_virtio_gpu_command(start_of_scratch_space(), sizeof(request), sizeof(response)); - VERIFY(response.type == static_cast(VirtIOGPUCtrlType::VIRTIO_GPU_RESP_OK_NODATA)); + VERIFY(response.type == static_cast(Protocol::CommandType::VIRTIO_GPU_RESP_OK_NODATA)); } -void VirtIOGPU::flush_displayed_image(VirtIOGPURect const& dirty_rect, VirtIOGPUResourceID resource_id) +void GPU::flush_displayed_image(Protocol::Rect const& dirty_rect, ResourceID resource_id) { VERIFY(m_operation_lock.is_locked()); - auto& request = *reinterpret_cast(m_scratch_space->vaddr().as_ptr()); - auto& response = *reinterpret_cast((m_scratch_space->vaddr().offset(sizeof(request)).as_ptr())); + auto& request = *reinterpret_cast(m_scratch_space->vaddr().as_ptr()); + auto& response = *reinterpret_cast((m_scratch_space->vaddr().offset(sizeof(request)).as_ptr())); - populate_virtio_gpu_request_header(request.header, VirtIOGPUCtrlType::VIRTIO_GPU_CMD_RESOURCE_FLUSH, VIRTIO_GPU_FLAG_FENCE); + populate_virtio_gpu_request_header(request.header, Protocol::CommandType::VIRTIO_GPU_CMD_RESOURCE_FLUSH, VIRTIO_GPU_FLAG_FENCE); request.resource_id = resource_id.value(); request.rect = dirty_rect; synchronous_virtio_gpu_command(start_of_scratch_space(), sizeof(request), sizeof(response)); - VERIFY(response.type == static_cast(VirtIOGPUCtrlType::VIRTIO_GPU_RESP_OK_NODATA)); + VERIFY(response.type == static_cast(Protocol::CommandType::VIRTIO_GPU_RESP_OK_NODATA)); } -void VirtIOGPU::synchronous_virtio_gpu_command(PhysicalAddress buffer_start, size_t request_size, size_t response_size) +void GPU::synchronous_virtio_gpu_command(PhysicalAddress buffer_start, size_t request_size, size_t response_size) { VERIFY(m_operation_lock.is_locked()); VERIFY(m_outstanding_request.is_empty()); @@ -233,7 +233,7 @@ void VirtIOGPU::synchronous_virtio_gpu_command(PhysicalAddress buffer_start, siz m_outstanding_request.wait_forever(); } -void VirtIOGPU::populate_virtio_gpu_request_header(VirtIOGPUCtrlHeader& header, VirtIOGPUCtrlType ctrl_type, u32 flags) +void GPU::populate_virtio_gpu_request_header(Protocol::ControlHeader& header, Protocol::CommandType ctrl_type, u32 flags) { header.type = static_cast(ctrl_type); header.flags = flags; @@ -242,32 +242,32 @@ void VirtIOGPU::populate_virtio_gpu_request_header(VirtIOGPUCtrlHeader& header, header.padding = 0; } -void VirtIOGPU::flush_dirty_window(VirtIOGPUScanoutID scanout, VirtIOGPURect const& dirty_rect, VirtIOGPUResourceID resource_id) +void GPU::flush_dirty_window(ScanoutID scanout, Protocol::Rect const& dirty_rect, ResourceID resource_id) { MutexLocker locker(m_operation_lock); transfer_framebuffer_data_to_host(scanout, dirty_rect, resource_id); flush_displayed_image(dirty_rect, resource_id); } -VirtIOGPUResourceID VirtIOGPU::allocate_resource_id() +ResourceID GPU::allocate_resource_id() { VERIFY(m_operation_lock.is_locked()); m_resource_id_counter = m_resource_id_counter.value() + 1; return m_resource_id_counter; } -void VirtIOGPU::delete_resource(VirtIOGPUResourceID resource_id) +void GPU::delete_resource(ResourceID resource_id) { VERIFY(m_operation_lock.is_locked()); - auto& request = *reinterpret_cast(m_scratch_space->vaddr().as_ptr()); - auto& response = *reinterpret_cast((m_scratch_space->vaddr().offset(sizeof(request)).as_ptr())); + auto& request = *reinterpret_cast(m_scratch_space->vaddr().as_ptr()); + auto& response = *reinterpret_cast((m_scratch_space->vaddr().offset(sizeof(request)).as_ptr())); - populate_virtio_gpu_request_header(request.header, VirtIOGPUCtrlType::VIRTIO_GPU_CMD_RESOURCE_UNREF, VIRTIO_GPU_FLAG_FENCE); + populate_virtio_gpu_request_header(request.header, Protocol::CommandType::VIRTIO_GPU_CMD_RESOURCE_UNREF, VIRTIO_GPU_FLAG_FENCE); request.resource_id = resource_id.value(); synchronous_virtio_gpu_command(start_of_scratch_space(), sizeof(request), sizeof(response)); - VERIFY(response.type == static_cast(VirtIOGPUCtrlType::VIRTIO_GPU_RESP_OK_NODATA)); + VERIFY(response.type == static_cast(Protocol::CommandType::VIRTIO_GPU_RESP_OK_NODATA)); } } diff --git a/Kernel/Graphics/VirtIOGPU/VirtIOGPU.h b/Kernel/Graphics/VirtIOGPU/VirtIOGPU.h index e0c79efb5f5..fd63f16581c 100644 --- a/Kernel/Graphics/VirtIOGPU/VirtIOGPU.h +++ b/Kernel/Graphics/VirtIOGPU/VirtIOGPU.h @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -16,165 +17,37 @@ #define VIRTIO_GPU_FLAG_FENCE (1 << 0) -#define VIRTIO_GPU_MAX_SCANOUTS 16 - #define CONTROLQ 0 #define CURSORQ 1 #define MAX_VIRTIOGPU_RESOLUTION_WIDTH 3840 #define MAX_VIRTIOGPU_RESOLUTION_HEIGHT 2160 -namespace Kernel::Graphics { +namespace Kernel::Graphics::VirtIOGPU { -class VirtIOGPUConsole; -class VirtIOFrameBufferDevice; +class Console; +class FrameBufferDevice; -TYPEDEF_DISTINCT_ORDERED_ID(u32, VirtIOGPUResourceID); -TYPEDEF_DISTINCT_ORDERED_ID(u32, VirtIOGPUScanoutID); +TYPEDEF_DISTINCT_ORDERED_ID(u32, ResourceID); +TYPEDEF_DISTINCT_ORDERED_ID(u32, ScanoutID); -enum class VirtIOGPUCtrlType : u32 { - /* 2d commands */ - VIRTIO_GPU_CMD_GET_DISPLAY_INFO = 0x0100, - VIRTIO_GPU_CMD_RESOURCE_CREATE_2D, - VIRTIO_GPU_CMD_RESOURCE_UNREF, - VIRTIO_GPU_CMD_SET_SCANOUT, - VIRTIO_GPU_CMD_RESOURCE_FLUSH, - VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D, - VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING, - VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING, - VIRTIO_GPU_CMD_GET_CAPSET_INFO, - VIRTIO_GPU_CMD_GET_CAPSET, - VIRTIO_GPU_CMD_GET_EDID, - - /* cursor commands */ - VIRTIO_GPU_CMD_UPDATE_CURSOR = 0x0300, - VIRTIO_GPU_CMD_MOVE_CURSOR, - - /* success responses */ - VIRTIO_GPU_RESP_OK_NODATA = 0x1100, - VIRTIO_GPU_RESP_OK_DISPLAY_INFO, - VIRTIO_GPU_RESP_OK_CAPSET_INFO, - VIRTIO_GPU_RESP_OK_CAPSET, - VIRTIO_GPU_RESP_OK_EDID, - - /* error responses */ - VIRTIO_GPU_RESP_ERR_UNSPEC = 0x1200, - VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY, - VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID, - VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID, - VIRTIO_GPU_RESP_ERR_INVALID_CONTEXT_ID, - VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER, -}; - -struct VirtIOGPUCtrlHeader { - u32 type; - u32 flags; - u64 fence_id; - u32 context_id; - u32 padding; -}; - -struct VirtIOGPURect { - u32 x; - u32 y; - u32 width; - u32 height; -}; - -struct VirtIOGPURespDisplayInfo { - VirtIOGPUCtrlHeader header; - struct VirtIOGPUDisplayOne { - VirtIOGPURect rect; - u32 enabled; - u32 flags; - } scanout_modes[VIRTIO_GPU_MAX_SCANOUTS]; -}; - -enum class VirtIOGPUFormats : u32 { - VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM = 1, - VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM = 2, - VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM = 3, - VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM = 4, - - VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM = 67, - VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM = 68, - - VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM = 121, - VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM = 134, -}; - -struct VirtIOGPUResourceCreate2D { - VirtIOGPUCtrlHeader header; - u32 resource_id; - u32 format; - u32 width; - u32 height; -}; - -struct VirtioGPUResourceUnref { - VirtIOGPUCtrlHeader header; - u32 resource_id; - u32 padding; -}; - -struct VirtIOGPUSetScanOut { - VirtIOGPUCtrlHeader header; - VirtIOGPURect rect; - u32 scanout_id; - u32 resource_id; -}; - -struct VirtIOGPUMemEntry { - u64 address; - u32 length; - u32 padding; -}; - -struct VirtIOGPUResourceAttachBacking { - VirtIOGPUCtrlHeader header; - u32 resource_id; - u32 num_entries; - VirtIOGPUMemEntry entries[]; -}; - -struct VirtIOGPUResourceDetachBacking { - VirtIOGPUCtrlHeader header; - u32 resource_id; - u32 padding; -}; - -struct VirtIOGPUTransferToHost2D { - VirtIOGPUCtrlHeader header; - VirtIOGPURect rect; - u64 offset; - u32 resource_id; - u32 padding; -}; - -struct VirtIOGPUResourceFlush { - VirtIOGPUCtrlHeader header; - VirtIOGPURect rect; - u32 resource_id; - u32 padding; -}; - -class VirtIOGPU final +class GPU final : public VirtIODevice - , public RefCounted { - friend class VirtIOFrameBufferDevice; + , public RefCounted { + friend class FrameBufferDevice; public: - VirtIOGPU(PCI::Address); - virtual ~VirtIOGPU() override; + GPU(PCI::Address); + virtual ~GPU() override; - void flush_dirty_window(VirtIOGPUScanoutID, VirtIOGPURect const& dirty_rect, VirtIOGPUResourceID); + void flush_dirty_window(ScanoutID, Protocol::Rect const& dirty_rect, ResourceID); - auto& display_info(VirtIOGPUScanoutID scanout) const + auto& display_info(ScanoutID scanout) const { VERIFY(scanout.value() < VIRTIO_GPU_MAX_SCANOUTS); return m_scanouts[scanout.value()].display_info; } - auto& display_info(VirtIOGPUScanoutID scanout) + auto& display_info(ScanoutID scanout) { VERIFY(scanout.value() < VIRTIO_GPU_MAX_SCANOUTS); return m_scanouts[scanout.value()].display_info; @@ -195,7 +68,7 @@ public: return IterationDecision::Continue; } - RefPtr default_console() + RefPtr default_console() { if (m_default_scanout.has_value()) return m_scanouts[m_default_scanout.value().value()].console; @@ -211,32 +84,32 @@ private: u32 get_pending_events(); void clear_pending_events(u32 event_bitmask); - VirtIOGPUResourceID allocate_resource_id(); + ResourceID allocate_resource_id(); PhysicalAddress start_of_scratch_space() const { return m_scratch_space->physical_page(0)->paddr(); } void synchronous_virtio_gpu_command(PhysicalAddress buffer_start, size_t request_size, size_t response_size); - void populate_virtio_gpu_request_header(VirtIOGPUCtrlHeader& header, VirtIOGPUCtrlType ctrl_type, u32 flags = 0); + void populate_virtio_gpu_request_header(Protocol::ControlHeader& header, Protocol::CommandType ctrl_type, u32 flags = 0); void query_display_information(); - VirtIOGPUResourceID create_2d_resource(VirtIOGPURect rect); - void delete_resource(VirtIOGPUResourceID resource_id); - void ensure_backing_storage(Region const&, size_t buffer_offset, size_t buffer_length, VirtIOGPUResourceID resource_id); - void detach_backing_storage(VirtIOGPUResourceID resource_id); - void set_scanout_resource(VirtIOGPUScanoutID scanout, VirtIOGPUResourceID resource_id, VirtIOGPURect rect); - void transfer_framebuffer_data_to_host(VirtIOGPUScanoutID scanout, VirtIOGPURect const& rect, VirtIOGPUResourceID resource_id); - void flush_displayed_image(VirtIOGPURect const& dirty_rect, VirtIOGPUResourceID resource_id); + ResourceID create_2d_resource(Protocol::Rect rect); + void delete_resource(ResourceID resource_id); + void ensure_backing_storage(Region const& region, size_t buffer_offset, size_t buffer_length, ResourceID resource_id); + void detach_backing_storage(ResourceID resource_id); + void set_scanout_resource(ScanoutID scanout, ResourceID resource_id, Protocol::Rect rect); + void transfer_framebuffer_data_to_host(ScanoutID scanout, Protocol::Rect const& rect, ResourceID resource_id); + void flush_displayed_image(Protocol::Rect const& dirty_rect, ResourceID resource_id); struct Scanout { - RefPtr framebuffer; - RefPtr console; - VirtIOGPURespDisplayInfo::VirtIOGPUDisplayOne display_info {}; + RefPtr framebuffer; + RefPtr console; + Protocol::DisplayInfoResponse::Display display_info {}; }; - Optional m_default_scanout; + Optional m_default_scanout; size_t m_num_scanouts { 0 }; Scanout m_scanouts[VIRTIO_GPU_MAX_SCANOUTS]; Configuration const* m_device_configuration { nullptr }; - VirtIOGPUResourceID m_resource_id_counter { 0 }; + ResourceID m_resource_id_counter { 0 }; // Synchronous commands WaitQueue m_outstanding_request;