mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-12 09:20:36 +00:00
Kernel: Put VirtIOGPU related types into a namespace
This commit is contained in:
parent
215f383b12
commit
1c77f80676
Notes:
sideshowbarker
2024-07-18 08:49:28 +09:00
Author: https://github.com/ccapitalK Commit: https://github.com/SerenityOS/serenity/commit/1c77f806762 Pull-request: https://github.com/SerenityOS/serenity/pull/8531
12 changed files with 326 additions and 300 deletions
|
@ -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
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include <Kernel/Graphics/GraphicsManagement.h>
|
||||
#include <Kernel/Graphics/Intel/NativeGraphicsAdapter.h>
|
||||
#include <Kernel/Graphics/VGACompatibleAdapter.h>
|
||||
#include <Kernel/Graphics/VirtIOGPU/VirtIOGraphicsAdapter.h>
|
||||
#include <Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h>
|
||||
#include <Kernel/IO.h>
|
||||
#include <Kernel/Multiboot.h>
|
||||
#include <Kernel/Sections.h>
|
||||
|
@ -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))
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include <Kernel/Graphics/Console/Console.h>
|
||||
#include <Kernel/Graphics/GraphicsDevice.h>
|
||||
#include <Kernel/Graphics/VGACompatibleAdapter.h>
|
||||
#include <Kernel/Graphics/VirtIOGPU/VirtIOGraphicsAdapter.h>
|
||||
#include <Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h>
|
||||
#include <Kernel/VM/Region.h>
|
||||
|
||||
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:
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.h>
|
||||
#include <Kernel/Graphics/VirtIOGPU/VirtIOGPUConsole.h>
|
||||
#include <Kernel/Graphics/VirtIOGPU/Console.h>
|
||||
#include <Kernel/Graphics/VirtIOGPU/FrameBufferDevice.h>
|
||||
#include <Kernel/WorkQueue.h>
|
||||
|
||||
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> VirtIOGPUConsole::initialize(RefPtr<VirtIOFrameBufferDevice> const& framebuffer_device)
|
||||
NonnullRefPtr<Console> Console::initialize(RefPtr<FrameBufferDevice> const& framebuffer_device)
|
||||
{
|
||||
return adopt_ref(*new VirtIOGPUConsole(framebuffer_device));
|
||||
return adopt_ref(*new Console(framebuffer_device));
|
||||
}
|
||||
|
||||
VirtIOGPUConsole::VirtIOGPUConsole(RefPtr<VirtIOFrameBufferDevice> const& framebuffer_device)
|
||||
Console::Console(RefPtr<FrameBufferDevice> 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<Timer> 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();
|
||||
}
|
|
@ -10,7 +10,7 @@
|
|||
#include <Kernel/Graphics/VirtIOGPU/VirtIOGPU.h>
|
||||
#include <Kernel/TimerQueue.h>
|
||||
|
||||
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<VirtIOGPUConsole> initialize(RefPtr<VirtIOFrameBufferDevice> const&);
|
||||
static NonnullRefPtr<Console> initialize(RefPtr<FrameBufferDevice> 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<VirtIOFrameBufferDevice> const&);
|
||||
RefPtr<VirtIOFrameBufferDevice> m_framebuffer_device;
|
||||
Console(RefPtr<FrameBufferDevice> const&);
|
||||
RefPtr<FrameBufferDevice> m_framebuffer_device;
|
||||
DirtyRect m_dirty_rect;
|
||||
};
|
||||
|
|
@ -5,12 +5,12 @@
|
|||
*/
|
||||
|
||||
#include <Kernel/Graphics/GraphicsManagement.h>
|
||||
#include <Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.h>
|
||||
#include <Kernel/Graphics/VirtIOGPU/FrameBufferDevice.h>
|
||||
#include <LibC/sys/ioctl_numbers.h>
|
||||
|
||||
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<Region*> VirtIOFrameBufferDevice::mmap(Process& process, FileDescription&, const Range& range, u64 offset, int prot, bool shared)
|
||||
KResultOr<Region*> FrameBufferDevice::mmap(Process& process, FileDescription&, const Range& range, u64 offset, int prot, bool shared)
|
||||
{
|
||||
REQUIRE_PROMISE(video);
|
||||
if (!shared)
|
||||
|
@ -262,7 +262,7 @@ KResultOr<Region*> 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;
|
||||
}
|
|
@ -11,20 +11,20 @@
|
|||
#include <Kernel/VirtIO/VirtIO.h>
|
||||
#include <Kernel/VirtIO/VirtIOQueue.h>
|
||||
|
||||
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<int, AK::memory_order_relaxed> m_last_set_buffer_index { 0 };
|
||||
Buffer m_main_buffer;
|
|
@ -8,25 +8,25 @@
|
|||
#include <Kernel/Graphics/Console/GenericFramebufferConsole.h>
|
||||
#include <Kernel/Graphics/GraphicsManagement.h>
|
||||
#include <Kernel/Graphics/VirtIOGPU/VirtIOGPU.h>
|
||||
#include <Kernel/Graphics/VirtIOGPU/VirtIOGraphicsAdapter.h>
|
||||
#include <Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h>
|
||||
|
||||
namespace Kernel::Graphics {
|
||||
namespace Kernel::Graphics::VirtIOGPU {
|
||||
|
||||
NonnullRefPtr<VirtIOGraphicsAdapter> VirtIOGraphicsAdapter::initialize(PCI::Address base_address)
|
||||
NonnullRefPtr<GraphicsAdapter> 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();
|
|
@ -6,24 +6,24 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.h>
|
||||
#include <Kernel/Graphics/VirtIOGPU/Console.h>
|
||||
#include <Kernel/Graphics/VirtIOGPU/FrameBufferDevice.h>
|
||||
#include <Kernel/Graphics/VirtIOGPU/VirtIOGPU.h>
|
||||
#include <Kernel/Graphics/VirtIOGPU/VirtIOGPUConsole.h>
|
||||
|
||||
namespace Kernel::Graphics {
|
||||
namespace Kernel::Graphics::VirtIOGPU {
|
||||
|
||||
class VirtIOGraphicsAdapter final
|
||||
class GraphicsAdapter final
|
||||
: public GraphicsDevice
|
||||
, public PCI::DeviceController {
|
||||
AK_MAKE_ETERNAL
|
||||
|
||||
public:
|
||||
static NonnullRefPtr<VirtIOGraphicsAdapter> initialize(PCI::Address);
|
||||
static NonnullRefPtr<GraphicsAdapter> 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<VirtIOGPU> m_gpu_device;
|
||||
RefPtr<GPU> m_gpu_device;
|
||||
bool m_created_framebuffer_devices { false };
|
||||
};
|
||||
|
153
Kernel/Graphics/VirtIOGPU/Protocol.h
Normal file
153
Kernel/Graphics/VirtIOGPU/Protocol.h
Normal file
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Sahan Fernando <sahan.h.fernando@gmail.com>
|
||||
*
|
||||
* 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;
|
||||
};
|
||||
|
||||
}
|
|
@ -4,18 +4,18 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.h>
|
||||
#include <Kernel/Graphics/VirtIOGPU/FrameBufferDevice.h>
|
||||
#include <Kernel/Graphics/VirtIOGPU/VirtIOGPU.h>
|
||||
#include <Kernel/Graphics/VirtIOGPU/VirtIOGPUConsole.h>
|
||||
#include <Kernel/Graphics/VirtIOGPU/Console.h>
|
||||
|
||||
#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<VirtIOGPUCtrlHeader*>(m_scratch_space->vaddr().as_ptr());
|
||||
auto& response = *reinterpret_cast<VirtIOGPURespDisplayInfo*>((m_scratch_space->vaddr().offset(sizeof(request)).as_ptr()));
|
||||
auto& request = *reinterpret_cast<Protocol::ControlHeader*>(m_scratch_space->vaddr().as_ptr());
|
||||
auto& response = *reinterpret_cast<Protocol::DisplayInfoResponse*>((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<VirtIOGPUResourceCreate2D*>(m_scratch_space->vaddr().as_ptr());
|
||||
auto& response = *reinterpret_cast<VirtIOGPUCtrlHeader*>((m_scratch_space->vaddr().offset(sizeof(request)).as_ptr()));
|
||||
auto& request = *reinterpret_cast<Protocol::ResourceCreate2D*>(m_scratch_space->vaddr().as_ptr());
|
||||
auto& response = *reinterpret_cast<Protocol::ControlHeader*>((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<u32>(VirtIOGPUFormats::VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM);
|
||||
request.format = static_cast<u32>(Protocol::TextureFormat::VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM);
|
||||
|
||||
synchronous_virtio_gpu_command(start_of_scratch_space(), sizeof(request), sizeof(response));
|
||||
|
||||
VERIFY(response.type == static_cast<u32>(VirtIOGPUCtrlType::VIRTIO_GPU_RESP_OK_NODATA));
|
||||
dbgln_if(VIRTIO_DEBUG, "VirtIOGPU: Allocated 2d resource with id {}", resource_id.value());
|
||||
VERIFY(response.type == static_cast<u32>(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<VirtIOGPUResourceAttachBacking*>(m_scratch_space->vaddr().as_ptr());
|
||||
const size_t header_block_size = sizeof(request) + num_mem_regions * sizeof(VirtIOGPUMemEntry);
|
||||
auto& response = *reinterpret_cast<VirtIOGPUCtrlHeader*>((m_scratch_space->vaddr().offset(header_block_size).as_ptr()));
|
||||
auto& request = *reinterpret_cast<Protocol::ResourceAttachBacking*>(m_scratch_space->vaddr().as_ptr());
|
||||
const size_t header_block_size = sizeof(request) + num_mem_regions * sizeof(Protocol::MemoryEntry);
|
||||
auto& response = *reinterpret_cast<Protocol::ControlHeader*>((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<u32>(VirtIOGPUCtrlType::VIRTIO_GPU_RESP_OK_NODATA));
|
||||
dbgln_if(VIRTIO_DEBUG, "VirtIOGPU: Allocated backing storage");
|
||||
VERIFY(response.type == static_cast<u32>(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<VirtIOGPUResourceDetachBacking*>(m_scratch_space->vaddr().as_ptr());
|
||||
auto& response = *reinterpret_cast<VirtIOGPUCtrlHeader*>((m_scratch_space->vaddr().offset(sizeof(request)).as_ptr()));
|
||||
auto& request = *reinterpret_cast<Protocol::ResourceDetachBacking*>(m_scratch_space->vaddr().as_ptr());
|
||||
auto& response = *reinterpret_cast<Protocol::ControlHeader*>((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<u32>(VirtIOGPUCtrlType::VIRTIO_GPU_RESP_OK_NODATA));
|
||||
dbgln_if(VIRTIO_DEBUG, "VirtIOGPU: Detached backing storage");
|
||||
VERIFY(response.type == static_cast<u32>(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<VirtIOGPUSetScanOut*>(m_scratch_space->vaddr().as_ptr());
|
||||
auto& response = *reinterpret_cast<VirtIOGPUCtrlHeader*>((m_scratch_space->vaddr().offset(sizeof(request)).as_ptr()));
|
||||
auto& request = *reinterpret_cast<Protocol::SetScanOut*>(m_scratch_space->vaddr().as_ptr());
|
||||
auto& response = *reinterpret_cast<Protocol::ControlHeader*>((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<u32>(VirtIOGPUCtrlType::VIRTIO_GPU_RESP_OK_NODATA));
|
||||
dbgln_if(VIRTIO_DEBUG, "VirtIOGPU: Set backing scanout");
|
||||
VERIFY(response.type == static_cast<u32>(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<VirtIOGPUTransferToHost2D*>(m_scratch_space->vaddr().as_ptr());
|
||||
auto& response = *reinterpret_cast<VirtIOGPUCtrlHeader*>((m_scratch_space->vaddr().offset(sizeof(request)).as_ptr()));
|
||||
auto& request = *reinterpret_cast<Protocol::TransferToHost2D*>(m_scratch_space->vaddr().as_ptr());
|
||||
auto& response = *reinterpret_cast<Protocol::ControlHeader*>((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<u32>(VirtIOGPUCtrlType::VIRTIO_GPU_RESP_OK_NODATA));
|
||||
VERIFY(response.type == static_cast<u32>(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<VirtIOGPUResourceFlush*>(m_scratch_space->vaddr().as_ptr());
|
||||
auto& response = *reinterpret_cast<VirtIOGPUCtrlHeader*>((m_scratch_space->vaddr().offset(sizeof(request)).as_ptr()));
|
||||
auto& request = *reinterpret_cast<Protocol::ResourceFlush*>(m_scratch_space->vaddr().as_ptr());
|
||||
auto& response = *reinterpret_cast<Protocol::ControlHeader*>((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<u32>(VirtIOGPUCtrlType::VIRTIO_GPU_RESP_OK_NODATA));
|
||||
VERIFY(response.type == static_cast<u32>(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<u32>(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<VirtioGPUResourceUnref*>(m_scratch_space->vaddr().as_ptr());
|
||||
auto& response = *reinterpret_cast<VirtIOGPUCtrlHeader*>((m_scratch_space->vaddr().offset(sizeof(request)).as_ptr()));
|
||||
auto& request = *reinterpret_cast<Protocol::ResourceUnref*>(m_scratch_space->vaddr().as_ptr());
|
||||
auto& response = *reinterpret_cast<Protocol::ControlHeader*>((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<u32>(VirtIOGPUCtrlType::VIRTIO_GPU_RESP_OK_NODATA));
|
||||
VERIFY(response.type == static_cast<u32>(Protocol::CommandType::VIRTIO_GPU_RESP_OK_NODATA));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <AK/DistinctNumeric.h>
|
||||
#include <Kernel/Devices/BlockDevice.h>
|
||||
#include <Kernel/Graphics/VirtIOGPU/Protocol.h>
|
||||
#include <Kernel/VirtIO/VirtIO.h>
|
||||
#include <Kernel/VirtIO/VirtIOQueue.h>
|
||||
|
||||
|
@ -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<VirtIOGPU> {
|
||||
friend class VirtIOFrameBufferDevice;
|
||||
, public RefCounted<GPU> {
|
||||
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<VirtIOGPUConsole> default_console()
|
||||
RefPtr<Console> 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<VirtIOFrameBufferDevice> framebuffer;
|
||||
RefPtr<VirtIOGPUConsole> console;
|
||||
VirtIOGPURespDisplayInfo::VirtIOGPUDisplayOne display_info {};
|
||||
RefPtr<FrameBufferDevice> framebuffer;
|
||||
RefPtr<Console> console;
|
||||
Protocol::DisplayInfoResponse::Display display_info {};
|
||||
};
|
||||
Optional<VirtIOGPUScanoutID> m_default_scanout;
|
||||
Optional<ScanoutID> 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;
|
||||
|
|
Loading…
Reference in a new issue