mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 09:07:35 +00:00
Kernel: Put VirtIOGPU related types into a namespace
This commit is contained in:
parent
215f383b12
commit
1c77f80676
12 changed files with 326 additions and 300 deletions
|
@ -71,10 +71,10 @@ set(KERNEL_SOURCES
|
||||||
Graphics/FramebufferDevice.cpp
|
Graphics/FramebufferDevice.cpp
|
||||||
Graphics/GraphicsManagement.cpp
|
Graphics/GraphicsManagement.cpp
|
||||||
Graphics/Intel/NativeGraphicsAdapter.cpp
|
Graphics/Intel/NativeGraphicsAdapter.cpp
|
||||||
Graphics/VirtIOGPU/VirtIOFrameBufferDevice.cpp
|
Graphics/VirtIOGPU/FrameBufferDevice.cpp
|
||||||
Graphics/VirtIOGPU/VirtIOGPUConsole.cpp
|
Graphics/VirtIOGPU/Console.cpp
|
||||||
Graphics/VirtIOGPU/VirtIOGPU.cpp
|
Graphics/VirtIOGPU/VirtIOGPU.cpp
|
||||||
Graphics/VirtIOGPU/VirtIOGraphicsAdapter.cpp
|
Graphics/VirtIOGPU/GraphicsAdapter.cpp
|
||||||
Graphics/VGACompatibleAdapter.cpp
|
Graphics/VGACompatibleAdapter.cpp
|
||||||
Storage/Partition/DiskPartition.cpp
|
Storage/Partition/DiskPartition.cpp
|
||||||
Storage/Partition/DiskPartitionMetadata.cpp
|
Storage/Partition/DiskPartitionMetadata.cpp
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include <Kernel/Graphics/GraphicsManagement.h>
|
#include <Kernel/Graphics/GraphicsManagement.h>
|
||||||
#include <Kernel/Graphics/Intel/NativeGraphicsAdapter.h>
|
#include <Kernel/Graphics/Intel/NativeGraphicsAdapter.h>
|
||||||
#include <Kernel/Graphics/VGACompatibleAdapter.h>
|
#include <Kernel/Graphics/VGACompatibleAdapter.h>
|
||||||
#include <Kernel/Graphics/VirtIOGPU/VirtIOGraphicsAdapter.h>
|
#include <Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h>
|
||||||
#include <Kernel/IO.h>
|
#include <Kernel/IO.h>
|
||||||
#include <Kernel/Multiboot.h>
|
#include <Kernel/Multiboot.h>
|
||||||
#include <Kernel/Sections.h>
|
#include <Kernel/Sections.h>
|
||||||
|
@ -91,7 +91,7 @@ UNMAP_AFTER_INIT bool GraphicsManagement::determine_and_initialize_graphics_devi
|
||||||
break;
|
break;
|
||||||
case PCI::VendorID::VirtIO:
|
case PCI::VendorID::VirtIO:
|
||||||
dmesgln("Graphics: Using VirtIO console");
|
dmesgln("Graphics: Using VirtIO console");
|
||||||
adapter = Graphics::VirtIOGraphicsAdapter::initialize(address);
|
adapter = Graphics::VirtIOGPU::GraphicsAdapter::initialize(address);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (!is_vga_compatible_pci_device(address))
|
if (!is_vga_compatible_pci_device(address))
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include <Kernel/Graphics/Console/Console.h>
|
#include <Kernel/Graphics/Console/Console.h>
|
||||||
#include <Kernel/Graphics/GraphicsDevice.h>
|
#include <Kernel/Graphics/GraphicsDevice.h>
|
||||||
#include <Kernel/Graphics/VGACompatibleAdapter.h>
|
#include <Kernel/Graphics/VGACompatibleAdapter.h>
|
||||||
#include <Kernel/Graphics/VirtIOGPU/VirtIOGraphicsAdapter.h>
|
#include <Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h>
|
||||||
#include <Kernel/VM/Region.h>
|
#include <Kernel/VM/Region.h>
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
@ -26,7 +26,7 @@ class GraphicsManagement {
|
||||||
friend class BochsGraphicsAdapter;
|
friend class BochsGraphicsAdapter;
|
||||||
friend class IntelNativeGraphicsAdapter;
|
friend class IntelNativeGraphicsAdapter;
|
||||||
friend class VGACompatibleAdapter;
|
friend class VGACompatibleAdapter;
|
||||||
friend class Graphics::VirtIOGraphicsAdapter;
|
friend class Graphics::VirtIOGPU::GraphicsAdapter;
|
||||||
AK_MAKE_ETERNAL
|
AK_MAKE_ETERNAL
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -4,11 +4,11 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.h>
|
#include <Kernel/Graphics/VirtIOGPU/Console.h>
|
||||||
#include <Kernel/Graphics/VirtIOGPU/VirtIOGPUConsole.h>
|
#include <Kernel/Graphics/VirtIOGPU/FrameBufferDevice.h>
|
||||||
#include <Kernel/WorkQueue.h>
|
#include <Kernel/WorkQueue.h>
|
||||||
|
|
||||||
namespace Kernel::Graphics {
|
namespace Kernel::Graphics::VirtIOGPU {
|
||||||
|
|
||||||
constexpr static AK::Time refresh_interval = AK::Time::from_milliseconds(16);
|
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())
|
: GenericFramebufferConsole(framebuffer_device->width(), framebuffer_device->height(), framebuffer_device->pitch())
|
||||||
, m_framebuffer_device(framebuffer_device)
|
, m_framebuffer_device(framebuffer_device)
|
||||||
{
|
{
|
||||||
enqueue_refresh_timer();
|
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);
|
auto did_set_resolution = m_framebuffer_device->try_to_set_resolution(width, height);
|
||||||
VERIFY(did_set_resolution);
|
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);
|
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());
|
NonnullRefPtr<Timer> refresh_timer = adopt_ref(*new Timer());
|
||||||
refresh_timer->setup(CLOCK_MONOTONIC, refresh_interval, [this]() {
|
refresh_timer->setup(CLOCK_MONOTONIC, refresh_interval, [this]() {
|
||||||
auto rect = m_dirty_rect;
|
auto rect = m_dirty_rect;
|
||||||
if (rect.is_dirty()) {
|
if (rect.is_dirty()) {
|
||||||
VirtIOGPURect dirty_rect {
|
Protocol::Rect dirty_rect {
|
||||||
.x = (u32)rect.x(),
|
.x = (u32)rect.x(),
|
||||||
.y = (u32)rect.y(),
|
.y = (u32)rect.y(),
|
||||||
.width = (u32)rect.width(),
|
.width = (u32)rect.width(),
|
||||||
|
@ -75,7 +75,7 @@ void VirtIOGPUConsole::enqueue_refresh_timer()
|
||||||
TimerQueue::the().add_timer(move(refresh_timer));
|
TimerQueue::the().add_timer(move(refresh_timer));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtIOGPUConsole::enable()
|
void Console::enable()
|
||||||
{
|
{
|
||||||
GenericFramebufferConsole::enable();
|
GenericFramebufferConsole::enable();
|
||||||
m_width = m_framebuffer_device->width();
|
m_width = m_framebuffer_device->width();
|
||||||
|
@ -84,7 +84,7 @@ void VirtIOGPUConsole::enable()
|
||||||
m_dirty_rect.union_rect(0, 0, m_width, m_height);
|
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();
|
return m_framebuffer_device->framebuffer_data();
|
||||||
}
|
}
|
|
@ -10,7 +10,7 @@
|
||||||
#include <Kernel/Graphics/VirtIOGPU/VirtIOGPU.h>
|
#include <Kernel/Graphics/VirtIOGPU/VirtIOGPU.h>
|
||||||
#include <Kernel/TimerQueue.h>
|
#include <Kernel/TimerQueue.h>
|
||||||
|
|
||||||
namespace Kernel::Graphics {
|
namespace Kernel::Graphics::VirtIOGPU {
|
||||||
|
|
||||||
class DirtyRect {
|
class DirtyRect {
|
||||||
public:
|
public:
|
||||||
|
@ -30,9 +30,9 @@ private:
|
||||||
size_t m_y1 { 0 };
|
size_t m_y1 { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
class VirtIOGPUConsole final : public GenericFramebufferConsole {
|
class Console final : public GenericFramebufferConsole {
|
||||||
public:
|
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 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;
|
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();
|
void enqueue_refresh_timer();
|
||||||
virtual u8* framebuffer_data() override;
|
virtual u8* framebuffer_data() override;
|
||||||
|
|
||||||
VirtIOGPUConsole(RefPtr<VirtIOFrameBufferDevice> const&);
|
Console(RefPtr<FrameBufferDevice> const&);
|
||||||
RefPtr<VirtIOFrameBufferDevice> m_framebuffer_device;
|
RefPtr<FrameBufferDevice> m_framebuffer_device;
|
||||||
DirtyRect m_dirty_rect;
|
DirtyRect m_dirty_rect;
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <Kernel/Graphics/GraphicsManagement.h>
|
#include <Kernel/Graphics/GraphicsManagement.h>
|
||||||
#include <Kernel/Graphics/VirtIOGPU/VirtIOFrameBufferDevice.h>
|
#include <Kernel/Graphics/VirtIOGPU/FrameBufferDevice.h>
|
||||||
#include <LibC/sys/ioctl_numbers.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())
|
: BlockDevice(29, GraphicsManagement::the().allocate_minor_device_number())
|
||||||
, m_gpu(virtio_gpu)
|
, m_gpu(virtio_gpu)
|
||||||
, m_scanout(scanout)
|
, m_scanout(scanout)
|
||||||
|
@ -19,11 +19,11 @@ VirtIOFrameBufferDevice::VirtIOFrameBufferDevice(VirtIOGPU& virtio_gpu, VirtIOGP
|
||||||
create_framebuffer();
|
create_framebuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtIOFrameBufferDevice::~VirtIOFrameBufferDevice()
|
FrameBufferDevice::~FrameBufferDevice()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtIOFrameBufferDevice::create_framebuffer()
|
void FrameBufferDevice::create_framebuffer()
|
||||||
{
|
{
|
||||||
// First delete any existing framebuffers to free the memory first
|
// First delete any existing framebuffers to free the memory first
|
||||||
m_framebuffer = nullptr;
|
m_framebuffer = nullptr;
|
||||||
|
@ -48,7 +48,7 @@ void VirtIOFrameBufferDevice::create_framebuffer()
|
||||||
create_buffer(m_back_buffer, m_buffer_size, m_buffer_size);
|
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_offset = framebuffer_offset;
|
||||||
buffer.framebuffer_data = m_framebuffer->vaddr().as_ptr() + 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;
|
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);
|
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);
|
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);
|
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);
|
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);
|
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)
|
if (width > MAX_VIRTIOGPU_RESOLUTION_WIDTH || height > MAX_VIRTIOGPU_RESOLUTION_HEIGHT)
|
||||||
return false;
|
return false;
|
||||||
|
@ -120,7 +120,7 @@ bool VirtIOFrameBufferDevice::try_to_set_resolution(size_t width, size_t height)
|
||||||
return true;
|
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;
|
auto& buffer = buffer_index == 0 ? m_main_buffer : m_back_buffer;
|
||||||
MutexLocker locker(m_gpu.operation_lock());
|
MutexLocker locker(m_gpu.operation_lock());
|
||||||
|
@ -132,7 +132,7 @@ void VirtIOFrameBufferDevice::set_buffer(int buffer_index)
|
||||||
buffer.dirty_rect = {};
|
buffer.dirty_rect = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
int VirtIOFrameBufferDevice::ioctl(FileDescription&, unsigned request, FlatPtr arg)
|
int FrameBufferDevice::ioctl(FileDescription&, unsigned request, FlatPtr arg)
|
||||||
{
|
{
|
||||||
REQUIRE_PROMISE(video);
|
REQUIRE_PROMISE(video);
|
||||||
switch (request) {
|
switch (request) {
|
||||||
|
@ -188,7 +188,7 @@ int VirtIOFrameBufferDevice::ioctl(FileDescription&, unsigned request, FlatPtr a
|
||||||
FBRect user_dirty_rect;
|
FBRect user_dirty_rect;
|
||||||
if (!copy_from_user(&user_dirty_rect, &user_flush_rects.rects[i]))
|
if (!copy_from_user(&user_dirty_rect, &user_flush_rects.rects[i]))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
VirtIOGPURect dirty_rect {
|
Protocol::Rect dirty_rect {
|
||||||
.x = user_dirty_rect.x,
|
.x = user_dirty_rect.x,
|
||||||
.y = user_dirty_rect.y,
|
.y = user_dirty_rect.y,
|
||||||
.width = user_dirty_rect.width,
|
.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);
|
REQUIRE_PROMISE(video);
|
||||||
if (!shared)
|
if (!shared)
|
||||||
|
@ -262,7 +262,7 @@ KResultOr<Region*> VirtIOFrameBufferDevice::mmap(Process& process, FileDescripti
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtIOFrameBufferDevice::deactivate_writes()
|
void FrameBufferDevice::deactivate_writes()
|
||||||
{
|
{
|
||||||
m_are_writes_active = false;
|
m_are_writes_active = false;
|
||||||
if (m_userspace_mmap_region) {
|
if (m_userspace_mmap_region) {
|
||||||
|
@ -276,7 +276,7 @@ void VirtIOFrameBufferDevice::deactivate_writes()
|
||||||
clear_to_black(buffer_from_index(0));
|
clear_to_black(buffer_from_index(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtIOFrameBufferDevice::activate_writes()
|
void FrameBufferDevice::activate_writes()
|
||||||
{
|
{
|
||||||
m_are_writes_active = true;
|
m_are_writes_active = true;
|
||||||
auto last_set_buffer_index = m_last_set_buffer_index.load();
|
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);
|
set_buffer(last_set_buffer_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtIOFrameBufferDevice::clear_to_black(Buffer& buffer)
|
void FrameBufferDevice::clear_to_black(Buffer& buffer)
|
||||||
{
|
{
|
||||||
auto& info = display_info();
|
auto& info = display_info();
|
||||||
size_t width = info.rect.width;
|
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] = {
|
static constexpr u8 colors[12][4] = {
|
||||||
{ 0xff, 0xff, 0xff, 0xff }, // White
|
{ 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");
|
dbgln_if(VIRTIO_DEBUG, "Finish drawing the pattern");
|
||||||
}
|
}
|
||||||
|
|
||||||
u8* VirtIOFrameBufferDevice::framebuffer_data()
|
u8* FrameBufferDevice::framebuffer_data()
|
||||||
{
|
{
|
||||||
return m_current_buffer->framebuffer_data;
|
return m_current_buffer->framebuffer_data;
|
||||||
}
|
}
|
|
@ -11,20 +11,20 @@
|
||||||
#include <Kernel/VirtIO/VirtIO.h>
|
#include <Kernel/VirtIO/VirtIO.h>
|
||||||
#include <Kernel/VirtIO/VirtIOQueue.h>
|
#include <Kernel/VirtIO/VirtIOQueue.h>
|
||||||
|
|
||||||
namespace Kernel::Graphics {
|
namespace Kernel::Graphics::VirtIOGPU {
|
||||||
|
|
||||||
class VirtIOFrameBufferDevice final : public BlockDevice {
|
class FrameBufferDevice final : public BlockDevice {
|
||||||
friend class VirtIOGPUConsole;
|
friend class Console;
|
||||||
struct Buffer {
|
struct Buffer {
|
||||||
size_t framebuffer_offset { 0 };
|
size_t framebuffer_offset { 0 };
|
||||||
u8* framebuffer_data { nullptr };
|
u8* framebuffer_data { nullptr };
|
||||||
VirtIOGPUResourceID resource_id { 0 };
|
Protocol::Rect dirty_rect {};
|
||||||
VirtIOGPURect dirty_rect {};
|
ResourceID resource_id { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VirtIOFrameBufferDevice(VirtIOGPU& virtio_gpu, VirtIOGPUScanoutID);
|
FrameBufferDevice(VirtIOGPU::GPU& virtio_gpu, ScanoutID);
|
||||||
virtual ~VirtIOFrameBufferDevice() override;
|
virtual ~FrameBufferDevice() override;
|
||||||
|
|
||||||
virtual void deactivate_writes();
|
virtual void deactivate_writes();
|
||||||
virtual void activate_writes();
|
virtual void activate_writes();
|
||||||
|
@ -42,9 +42,9 @@ public:
|
||||||
return page_round_up(sizeof(u32) * width * height);
|
return page_round_up(sizeof(u32) * width * height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void flush_dirty_window(VirtIOGPURect const&, Buffer&);
|
void flush_dirty_window(Protocol::Rect const&, Buffer&);
|
||||||
void transfer_framebuffer_data_to_host(VirtIOGPURect const&, Buffer&);
|
void transfer_framebuffer_data_to_host(Protocol::Rect const&, Buffer&);
|
||||||
void flush_displayed_image(VirtIOGPURect const&, Buffer&);
|
void flush_displayed_image(Protocol::Rect const&, Buffer&);
|
||||||
|
|
||||||
void draw_ntsc_test_pattern(Buffer&);
|
void draw_ntsc_test_pattern(Buffer&);
|
||||||
|
|
||||||
|
@ -53,8 +53,8 @@ public:
|
||||||
private:
|
private:
|
||||||
virtual StringView class_name() const override { return "VirtIOFrameBuffer"; }
|
virtual StringView class_name() const override { return "VirtIOFrameBuffer"; }
|
||||||
|
|
||||||
VirtIOGPURespDisplayInfo::VirtIOGPUDisplayOne const& display_info() const;
|
Protocol::DisplayInfoResponse::Display const& display_info() const;
|
||||||
VirtIOGPURespDisplayInfo::VirtIOGPUDisplayOne& display_info();
|
Protocol::DisplayInfoResponse::Display& display_info();
|
||||||
|
|
||||||
void create_framebuffer();
|
void create_framebuffer();
|
||||||
void create_buffer(Buffer&, size_t, size_t);
|
void create_buffer(Buffer&, size_t, size_t);
|
||||||
|
@ -82,8 +82,8 @@ private:
|
||||||
}
|
}
|
||||||
Buffer& current_buffer() const { return *m_current_buffer; }
|
Buffer& current_buffer() const { return *m_current_buffer; }
|
||||||
|
|
||||||
VirtIOGPU& m_gpu;
|
GPU& m_gpu;
|
||||||
const VirtIOGPUScanoutID m_scanout;
|
const ScanoutID m_scanout;
|
||||||
Buffer* m_current_buffer { nullptr };
|
Buffer* m_current_buffer { nullptr };
|
||||||
Atomic<int, AK::memory_order_relaxed> m_last_set_buffer_index { 0 };
|
Atomic<int, AK::memory_order_relaxed> m_last_set_buffer_index { 0 };
|
||||||
Buffer m_main_buffer;
|
Buffer m_main_buffer;
|
|
@ -8,25 +8,25 @@
|
||||||
#include <Kernel/Graphics/Console/GenericFramebufferConsole.h>
|
#include <Kernel/Graphics/Console/GenericFramebufferConsole.h>
|
||||||
#include <Kernel/Graphics/GraphicsManagement.h>
|
#include <Kernel/Graphics/GraphicsManagement.h>
|
||||||
#include <Kernel/Graphics/VirtIOGPU/VirtIOGPU.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);
|
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)
|
: 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);
|
VERIFY(!m_created_framebuffer_devices);
|
||||||
m_gpu_device->create_framebuffer_devices();
|
m_gpu_device->create_framebuffer_devices();
|
||||||
m_created_framebuffer_devices = true;
|
m_created_framebuffer_devices = true;
|
||||||
|
@ -35,9 +35,9 @@ void VirtIOGraphicsAdapter::initialize_framebuffer_devices()
|
||||||
GraphicsManagement::the().m_console = m_gpu_device->default_console();
|
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) {
|
m_gpu_device->for_each_framebuffer([&](auto& framebuffer, auto& console) {
|
||||||
framebuffer.deactivate_writes();
|
framebuffer.deactivate_writes();
|
||||||
console.enable();
|
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) {
|
m_gpu_device->for_each_framebuffer([&](auto& framebuffer, auto& console) {
|
||||||
console.disable();
|
console.disable();
|
||||||
framebuffer.activate_writes();
|
framebuffer.activate_writes();
|
|
@ -6,24 +6,24 @@
|
||||||
|
|
||||||
#pragma once
|
#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/VirtIOGPU.h>
|
||||||
#include <Kernel/Graphics/VirtIOGPU/VirtIOGPUConsole.h>
|
|
||||||
|
|
||||||
namespace Kernel::Graphics {
|
namespace Kernel::Graphics::VirtIOGPU {
|
||||||
|
|
||||||
class VirtIOGraphicsAdapter final
|
class GraphicsAdapter final
|
||||||
: public GraphicsDevice
|
: public GraphicsDevice
|
||||||
, public PCI::DeviceController {
|
, public PCI::DeviceController {
|
||||||
AK_MAKE_ETERNAL
|
AK_MAKE_ETERNAL
|
||||||
|
|
||||||
public:
|
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; }
|
virtual bool framebuffer_devices_initialized() const override { return m_created_framebuffer_devices; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit VirtIOGraphicsAdapter(PCI::Address base_address);
|
explicit GraphicsAdapter(PCI::Address base_address);
|
||||||
|
|
||||||
virtual void initialize_framebuffer_devices() override;
|
virtual void initialize_framebuffer_devices() override;
|
||||||
virtual Type type() const override { return Type::Raw; }
|
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 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; }
|
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 };
|
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
|
* 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/VirtIOGPU.h>
|
||||||
#include <Kernel/Graphics/VirtIOGPU/VirtIOGPUConsole.h>
|
#include <Kernel/Graphics/VirtIOGPU/Console.h>
|
||||||
|
|
||||||
#define DEVICE_EVENTS_READ 0x0
|
#define DEVICE_EVENTS_READ 0x0
|
||||||
#define DEVICE_EVENTS_CLEAR 0x4
|
#define DEVICE_EVENTS_CLEAR 0x4
|
||||||
#define DEVICE_NUM_SCANOUTS 0x8
|
#define DEVICE_NUM_SCANOUTS 0x8
|
||||||
|
|
||||||
namespace Kernel::Graphics {
|
namespace Kernel::Graphics::VirtIOGPU {
|
||||||
|
|
||||||
VirtIOGPU::VirtIOGPU(PCI::Address address)
|
GPU::GPU(PCI::Address address)
|
||||||
: VirtIODevice(address, "VirtIOGPU")
|
: VirtIODevice(address, "GPU")
|
||||||
, m_scratch_space(MM.allocate_contiguous_kernel_region(32 * PAGE_SIZE, "VirtGPU Scratch Space", Region::Access::Read | Region::Access::Write))
|
, m_scratch_space(MM.allocate_contiguous_kernel_region(32 * PAGE_SIZE, "VirtGPU Scratch Space", Region::Access::Read | Region::Access::Write))
|
||||||
{
|
{
|
||||||
VERIFY(!!m_scratch_space);
|
VERIFY(!!m_scratch_space);
|
||||||
|
@ -24,16 +24,16 @@ VirtIOGPU::VirtIOGPU(PCI::Address address)
|
||||||
bool success = negotiate_features([&](u64 supported_features) {
|
bool success = negotiate_features([&](u64 supported_features) {
|
||||||
u64 negotiated = 0;
|
u64 negotiated = 0;
|
||||||
if (is_feature_set(supported_features, VIRTIO_GPU_F_VIRGL))
|
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))
|
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;
|
return negotiated;
|
||||||
});
|
});
|
||||||
if (success) {
|
if (success) {
|
||||||
read_config_atomic([&]() {
|
read_config_atomic([&]() {
|
||||||
m_num_scanouts = config_read32(*cfg, DEVICE_NUM_SCANOUTS);
|
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
|
success = setup_queues(2); // CONTROLQ + CURSORQ
|
||||||
}
|
}
|
||||||
VERIFY(success);
|
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++) {
|
for (size_t i = 0; i < min(m_num_scanouts, VIRTIO_GPU_MAX_SCANOUTS); i++) {
|
||||||
auto& scanout = m_scanouts[i];
|
auto& scanout = m_scanouts[i];
|
||||||
scanout.framebuffer = adopt_ref(*new VirtIOFrameBufferDevice(*this, i));
|
scanout.framebuffer = adopt_ref(*new VirtIOGPU::FrameBufferDevice(*this, i));
|
||||||
scanout.console = Kernel::Graphics::VirtIOGPUConsole::initialize(scanout.framebuffer);
|
scanout.console = Kernel::Graphics::VirtIOGPU::Console::initialize(scanout.framebuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VirtIOGPU::handle_device_config_change()
|
bool GPU::handle_device_config_change()
|
||||||
{
|
{
|
||||||
return false;
|
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);
|
VERIFY(queue_index == CONTROLQ);
|
||||||
|
|
||||||
auto& queue = get_queue(CONTROLQ);
|
auto& queue = get_queue(CONTROLQ);
|
||||||
|
@ -75,23 +75,23 @@ void VirtIOGPU::handle_queue_update(u16 queue_index)
|
||||||
m_outstanding_request.wake_all();
|
m_outstanding_request.wake_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 VirtIOGPU::get_pending_events()
|
u32 GPU::get_pending_events()
|
||||||
{
|
{
|
||||||
return config_read32(*m_device_configuration, DEVICE_EVENTS_READ);
|
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);
|
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());
|
VERIFY(m_operation_lock.is_locked());
|
||||||
auto& request = *reinterpret_cast<VirtIOGPUCtrlHeader*>(m_scratch_space->vaddr().as_ptr());
|
auto& request = *reinterpret_cast<Protocol::ControlHeader*>(m_scratch_space->vaddr().as_ptr());
|
||||||
auto& response = *reinterpret_cast<VirtIOGPURespDisplayInfo*>((m_scratch_space->vaddr().offset(sizeof(request)).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));
|
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());
|
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());
|
VERIFY(m_operation_lock.is_locked());
|
||||||
auto& request = *reinterpret_cast<VirtIOGPUResourceCreate2D*>(m_scratch_space->vaddr().as_ptr());
|
auto& request = *reinterpret_cast<Protocol::ResourceCreate2D*>(m_scratch_space->vaddr().as_ptr());
|
||||||
auto& response = *reinterpret_cast<VirtIOGPUCtrlHeader*>((m_scratch_space->vaddr().offset(sizeof(request)).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();
|
auto resource_id = allocate_resource_id();
|
||||||
request.resource_id = resource_id.value();
|
request.resource_id = resource_id.value();
|
||||||
request.width = rect.width;
|
request.width = rect.width;
|
||||||
request.height = rect.height;
|
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));
|
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));
|
||||||
dbgln_if(VIRTIO_DEBUG, "VirtIOGPU: Allocated 2d resource with id {}", resource_id.value());
|
dbgln_if(VIRTIO_DEBUG, "GPU: Allocated 2d resource with id {}", resource_id.value());
|
||||||
return resource_id;
|
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());
|
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;
|
size_t num_mem_regions = buffer_length / PAGE_SIZE;
|
||||||
|
|
||||||
// Send request
|
// Send request
|
||||||
auto& request = *reinterpret_cast<VirtIOGPUResourceAttachBacking*>(m_scratch_space->vaddr().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(VirtIOGPUMemEntry);
|
const size_t header_block_size = sizeof(request) + num_mem_regions * sizeof(Protocol::MemoryEntry);
|
||||||
auto& response = *reinterpret_cast<VirtIOGPUCtrlHeader*>((m_scratch_space->vaddr().offset(header_block_size).as_ptr()));
|
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.resource_id = resource_id.value();
|
||||||
request.num_entries = num_mem_regions;
|
request.num_entries = num_mem_regions;
|
||||||
for (size_t i = 0; i < num_mem_regions; ++i) {
|
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));
|
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));
|
VERIFY(response.type == static_cast<u32>(Protocol::CommandType::VIRTIO_GPU_RESP_OK_NODATA));
|
||||||
dbgln_if(VIRTIO_DEBUG, "VirtIOGPU: Allocated backing storage");
|
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());
|
VERIFY(m_operation_lock.is_locked());
|
||||||
auto& request = *reinterpret_cast<VirtIOGPUResourceDetachBacking*>(m_scratch_space->vaddr().as_ptr());
|
auto& request = *reinterpret_cast<Protocol::ResourceDetachBacking*>(m_scratch_space->vaddr().as_ptr());
|
||||||
auto& response = *reinterpret_cast<VirtIOGPUCtrlHeader*>((m_scratch_space->vaddr().offset(sizeof(request)).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();
|
request.resource_id = resource_id.value();
|
||||||
|
|
||||||
synchronous_virtio_gpu_command(start_of_scratch_space(), sizeof(request), sizeof(response));
|
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));
|
||||||
dbgln_if(VIRTIO_DEBUG, "VirtIOGPU: Detached backing storage");
|
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());
|
VERIFY(m_operation_lock.is_locked());
|
||||||
auto& request = *reinterpret_cast<VirtIOGPUSetScanOut*>(m_scratch_space->vaddr().as_ptr());
|
auto& request = *reinterpret_cast<Protocol::SetScanOut*>(m_scratch_space->vaddr().as_ptr());
|
||||||
auto& response = *reinterpret_cast<VirtIOGPUCtrlHeader*>((m_scratch_space->vaddr().offset(sizeof(request)).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.resource_id = resource_id.value();
|
||||||
request.scanout_id = scanout.value();
|
request.scanout_id = scanout.value();
|
||||||
request.rect = rect;
|
request.rect = rect;
|
||||||
|
|
||||||
synchronous_virtio_gpu_command(start_of_scratch_space(), sizeof(request), sizeof(response));
|
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));
|
||||||
dbgln_if(VIRTIO_DEBUG, "VirtIOGPU: Set backing scanout");
|
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());
|
VERIFY(m_operation_lock.is_locked());
|
||||||
auto& request = *reinterpret_cast<VirtIOGPUTransferToHost2D*>(m_scratch_space->vaddr().as_ptr());
|
auto& request = *reinterpret_cast<Protocol::TransferToHost2D*>(m_scratch_space->vaddr().as_ptr());
|
||||||
auto& response = *reinterpret_cast<VirtIOGPUCtrlHeader*>((m_scratch_space->vaddr().offset(sizeof(request)).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.offset = (dirty_rect.x + (dirty_rect.y * m_scanouts[scanout.value()].display_info.rect.width)) * sizeof(u32);
|
||||||
request.resource_id = resource_id.value();
|
request.resource_id = resource_id.value();
|
||||||
request.rect = dirty_rect;
|
request.rect = dirty_rect;
|
||||||
|
|
||||||
synchronous_virtio_gpu_command(start_of_scratch_space(), sizeof(request), sizeof(response));
|
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());
|
VERIFY(m_operation_lock.is_locked());
|
||||||
auto& request = *reinterpret_cast<VirtIOGPUResourceFlush*>(m_scratch_space->vaddr().as_ptr());
|
auto& request = *reinterpret_cast<Protocol::ResourceFlush*>(m_scratch_space->vaddr().as_ptr());
|
||||||
auto& response = *reinterpret_cast<VirtIOGPUCtrlHeader*>((m_scratch_space->vaddr().offset(sizeof(request)).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.resource_id = resource_id.value();
|
||||||
request.rect = dirty_rect;
|
request.rect = dirty_rect;
|
||||||
|
|
||||||
synchronous_virtio_gpu_command(start_of_scratch_space(), sizeof(request), sizeof(response));
|
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_operation_lock.is_locked());
|
||||||
VERIFY(m_outstanding_request.is_empty());
|
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();
|
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.type = static_cast<u32>(ctrl_type);
|
||||||
header.flags = flags;
|
header.flags = flags;
|
||||||
|
@ -242,32 +242,32 @@ void VirtIOGPU::populate_virtio_gpu_request_header(VirtIOGPUCtrlHeader& header,
|
||||||
header.padding = 0;
|
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);
|
MutexLocker locker(m_operation_lock);
|
||||||
transfer_framebuffer_data_to_host(scanout, dirty_rect, resource_id);
|
transfer_framebuffer_data_to_host(scanout, dirty_rect, resource_id);
|
||||||
flush_displayed_image(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());
|
VERIFY(m_operation_lock.is_locked());
|
||||||
m_resource_id_counter = m_resource_id_counter.value() + 1;
|
m_resource_id_counter = m_resource_id_counter.value() + 1;
|
||||||
return m_resource_id_counter;
|
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());
|
VERIFY(m_operation_lock.is_locked());
|
||||||
auto& request = *reinterpret_cast<VirtioGPUResourceUnref*>(m_scratch_space->vaddr().as_ptr());
|
auto& request = *reinterpret_cast<Protocol::ResourceUnref*>(m_scratch_space->vaddr().as_ptr());
|
||||||
auto& response = *reinterpret_cast<VirtIOGPUCtrlHeader*>((m_scratch_space->vaddr().offset(sizeof(request)).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();
|
request.resource_id = resource_id.value();
|
||||||
|
|
||||||
synchronous_virtio_gpu_command(start_of_scratch_space(), sizeof(request), sizeof(response));
|
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 <AK/DistinctNumeric.h>
|
||||||
#include <Kernel/Devices/BlockDevice.h>
|
#include <Kernel/Devices/BlockDevice.h>
|
||||||
|
#include <Kernel/Graphics/VirtIOGPU/Protocol.h>
|
||||||
#include <Kernel/VirtIO/VirtIO.h>
|
#include <Kernel/VirtIO/VirtIO.h>
|
||||||
#include <Kernel/VirtIO/VirtIOQueue.h>
|
#include <Kernel/VirtIO/VirtIOQueue.h>
|
||||||
|
|
||||||
|
@ -16,165 +17,37 @@
|
||||||
|
|
||||||
#define VIRTIO_GPU_FLAG_FENCE (1 << 0)
|
#define VIRTIO_GPU_FLAG_FENCE (1 << 0)
|
||||||
|
|
||||||
#define VIRTIO_GPU_MAX_SCANOUTS 16
|
|
||||||
|
|
||||||
#define CONTROLQ 0
|
#define CONTROLQ 0
|
||||||
#define CURSORQ 1
|
#define CURSORQ 1
|
||||||
|
|
||||||
#define MAX_VIRTIOGPU_RESOLUTION_WIDTH 3840
|
#define MAX_VIRTIOGPU_RESOLUTION_WIDTH 3840
|
||||||
#define MAX_VIRTIOGPU_RESOLUTION_HEIGHT 2160
|
#define MAX_VIRTIOGPU_RESOLUTION_HEIGHT 2160
|
||||||
|
|
||||||
namespace Kernel::Graphics {
|
namespace Kernel::Graphics::VirtIOGPU {
|
||||||
|
|
||||||
class VirtIOGPUConsole;
|
class Console;
|
||||||
class VirtIOFrameBufferDevice;
|
class FrameBufferDevice;
|
||||||
|
|
||||||
TYPEDEF_DISTINCT_ORDERED_ID(u32, VirtIOGPUResourceID);
|
TYPEDEF_DISTINCT_ORDERED_ID(u32, ResourceID);
|
||||||
TYPEDEF_DISTINCT_ORDERED_ID(u32, VirtIOGPUScanoutID);
|
TYPEDEF_DISTINCT_ORDERED_ID(u32, ScanoutID);
|
||||||
|
|
||||||
enum class VirtIOGPUCtrlType : u32 {
|
class GPU final
|
||||||
/* 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
|
|
||||||
: public VirtIODevice
|
: public VirtIODevice
|
||||||
, public RefCounted<VirtIOGPU> {
|
, public RefCounted<GPU> {
|
||||||
friend class VirtIOFrameBufferDevice;
|
friend class FrameBufferDevice;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VirtIOGPU(PCI::Address);
|
GPU(PCI::Address);
|
||||||
virtual ~VirtIOGPU() override;
|
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);
|
VERIFY(scanout.value() < VIRTIO_GPU_MAX_SCANOUTS);
|
||||||
return m_scanouts[scanout.value()].display_info;
|
return m_scanouts[scanout.value()].display_info;
|
||||||
}
|
}
|
||||||
auto& display_info(VirtIOGPUScanoutID scanout)
|
auto& display_info(ScanoutID scanout)
|
||||||
{
|
{
|
||||||
VERIFY(scanout.value() < VIRTIO_GPU_MAX_SCANOUTS);
|
VERIFY(scanout.value() < VIRTIO_GPU_MAX_SCANOUTS);
|
||||||
return m_scanouts[scanout.value()].display_info;
|
return m_scanouts[scanout.value()].display_info;
|
||||||
|
@ -195,7 +68,7 @@ public:
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<VirtIOGPUConsole> default_console()
|
RefPtr<Console> default_console()
|
||||||
{
|
{
|
||||||
if (m_default_scanout.has_value())
|
if (m_default_scanout.has_value())
|
||||||
return m_scanouts[m_default_scanout.value().value()].console;
|
return m_scanouts[m_default_scanout.value().value()].console;
|
||||||
|
@ -211,32 +84,32 @@ private:
|
||||||
u32 get_pending_events();
|
u32 get_pending_events();
|
||||||
void clear_pending_events(u32 event_bitmask);
|
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(); }
|
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 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();
|
void query_display_information();
|
||||||
VirtIOGPUResourceID create_2d_resource(VirtIOGPURect rect);
|
ResourceID create_2d_resource(Protocol::Rect rect);
|
||||||
void delete_resource(VirtIOGPUResourceID resource_id);
|
void delete_resource(ResourceID resource_id);
|
||||||
void ensure_backing_storage(Region const&, size_t buffer_offset, size_t buffer_length, VirtIOGPUResourceID resource_id);
|
void ensure_backing_storage(Region const& region, size_t buffer_offset, size_t buffer_length, ResourceID resource_id);
|
||||||
void detach_backing_storage(VirtIOGPUResourceID resource_id);
|
void detach_backing_storage(ResourceID resource_id);
|
||||||
void set_scanout_resource(VirtIOGPUScanoutID scanout, VirtIOGPUResourceID resource_id, VirtIOGPURect rect);
|
void set_scanout_resource(ScanoutID scanout, ResourceID resource_id, Protocol::Rect rect);
|
||||||
void transfer_framebuffer_data_to_host(VirtIOGPUScanoutID scanout, VirtIOGPURect const& rect, VirtIOGPUResourceID resource_id);
|
void transfer_framebuffer_data_to_host(ScanoutID scanout, Protocol::Rect const& rect, ResourceID resource_id);
|
||||||
void flush_displayed_image(VirtIOGPURect const& dirty_rect, VirtIOGPUResourceID resource_id);
|
void flush_displayed_image(Protocol::Rect const& dirty_rect, ResourceID resource_id);
|
||||||
|
|
||||||
struct Scanout {
|
struct Scanout {
|
||||||
RefPtr<VirtIOFrameBufferDevice> framebuffer;
|
RefPtr<FrameBufferDevice> framebuffer;
|
||||||
RefPtr<VirtIOGPUConsole> console;
|
RefPtr<Console> console;
|
||||||
VirtIOGPURespDisplayInfo::VirtIOGPUDisplayOne display_info {};
|
Protocol::DisplayInfoResponse::Display display_info {};
|
||||||
};
|
};
|
||||||
Optional<VirtIOGPUScanoutID> m_default_scanout;
|
Optional<ScanoutID> m_default_scanout;
|
||||||
size_t m_num_scanouts { 0 };
|
size_t m_num_scanouts { 0 };
|
||||||
Scanout m_scanouts[VIRTIO_GPU_MAX_SCANOUTS];
|
Scanout m_scanouts[VIRTIO_GPU_MAX_SCANOUTS];
|
||||||
|
|
||||||
Configuration const* m_device_configuration { nullptr };
|
Configuration const* m_device_configuration { nullptr };
|
||||||
|
|
||||||
VirtIOGPUResourceID m_resource_id_counter { 0 };
|
ResourceID m_resource_id_counter { 0 };
|
||||||
|
|
||||||
// Synchronous commands
|
// Synchronous commands
|
||||||
WaitQueue m_outstanding_request;
|
WaitQueue m_outstanding_request;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue