summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/Graphics/Bochs/DisplayConnector.cpp24
-rw-r--r--Kernel/Graphics/Bochs/DisplayConnector.h8
-rw-r--r--Kernel/Graphics/Bochs/GraphicsAdapter.cpp5
-rw-r--r--Kernel/Graphics/Bochs/QEMUDisplayConnector.cpp13
-rw-r--r--Kernel/Graphics/Bochs/QEMUDisplayConnector.h4
-rw-r--r--Kernel/Graphics/DisplayConnector.cpp65
-rw-r--r--Kernel/Graphics/DisplayConnector.h27
-rw-r--r--Kernel/Graphics/Intel/NativeDisplayConnector.cpp31
-rw-r--r--Kernel/Graphics/Intel/NativeDisplayConnector.h8
-rw-r--r--Kernel/Graphics/Intel/NativeGraphicsAdapter.cpp3
-rw-r--r--Kernel/Graphics/VGA/DisplayConnector.cpp18
-rw-r--r--Kernel/Graphics/VGA/DisplayConnector.h4
-rw-r--r--Kernel/Graphics/VMWare/DisplayConnector.cpp26
-rw-r--r--Kernel/Graphics/VMWare/DisplayConnector.h10
-rw-r--r--Kernel/Graphics/VMWare/GraphicsAdapter.cpp4
-rw-r--r--Kernel/Graphics/VirtIOGPU/DisplayConnector.cpp245
-rw-r--r--Kernel/Graphics/VirtIOGPU/DisplayConnector.h56
-rw-r--r--Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp77
-rw-r--r--Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h22
19 files changed, 309 insertions, 341 deletions
diff --git a/Kernel/Graphics/Bochs/DisplayConnector.cpp b/Kernel/Graphics/Bochs/DisplayConnector.cpp
index c6bc1b8c3c..5e9c74711c 100644
--- a/Kernel/Graphics/Bochs/DisplayConnector.cpp
+++ b/Kernel/Graphics/Bochs/DisplayConnector.cpp
@@ -14,9 +14,9 @@
namespace Kernel {
-NonnullRefPtr<BochsDisplayConnector> BochsDisplayConnector::must_create(PhysicalAddress framebuffer_address)
+NonnullRefPtr<BochsDisplayConnector> BochsDisplayConnector::must_create(PhysicalAddress framebuffer_address, size_t framebuffer_resource_size)
{
- auto device_or_error = DeviceManagement::try_create_device<BochsDisplayConnector>(framebuffer_address);
+ auto device_or_error = DeviceManagement::try_create_device<BochsDisplayConnector>(framebuffer_address, framebuffer_resource_size);
VERIFY(!device_or_error.is_error());
auto connector = device_or_error.release_value();
MUST(connector->create_attached_framebuffer_console());
@@ -24,20 +24,15 @@ NonnullRefPtr<BochsDisplayConnector> BochsDisplayConnector::must_create(Physical
return connector;
}
-BochsDisplayConnector::BochsDisplayConnector(PhysicalAddress framebuffer_address)
- : DisplayConnector()
- , m_framebuffer_address(framebuffer_address)
+BochsDisplayConnector::BochsDisplayConnector(PhysicalAddress framebuffer_address, size_t framebuffer_resource_size)
+ : DisplayConnector(framebuffer_address, framebuffer_resource_size, false)
{
}
ErrorOr<void> BochsDisplayConnector::create_attached_framebuffer_console()
{
- auto rounded_size = TRY(Memory::page_round_up(1024 * sizeof(u32) * 768 * 2));
- m_framebuffer_region = TRY(MM.allocate_kernel_region(m_framebuffer_address.page_base(), rounded_size, "Framebuffer"sv, Memory::Region::Access::ReadWrite));
- [[maybe_unused]] auto result = m_framebuffer_region->set_write_combine(true);
- m_framebuffer_data = m_framebuffer_region->vaddr().offset(m_framebuffer_address.offset_in_page()).as_ptr();
// We assume safe resolution is 1024x768x32
- m_framebuffer_console = Graphics::ContiguousFramebufferConsole::initialize(m_framebuffer_address, 1024, 768, 1024 * sizeof(u32));
+ m_framebuffer_console = Graphics::ContiguousFramebufferConsole::initialize(m_framebuffer_address.value(), 1024, 768, 1024 * sizeof(u32));
GraphicsManagement::the().set_console(*m_framebuffer_console);
return {};
}
@@ -59,15 +54,6 @@ BochsDisplayConnector::IndexID BochsDisplayConnector::index_id() const
return get_register_with_io(0);
}
-ErrorOr<size_t> BochsDisplayConnector::write_to_first_surface(u64 offset, UserOrKernelBuffer const& buffer, size_t length)
-{
- VERIFY(m_control_lock.is_locked());
- if (offset + length > m_framebuffer_region->size())
- return Error::from_errno(EOVERFLOW);
- TRY(buffer.read(m_framebuffer_data + offset, 0, length));
- return length;
-}
-
void BochsDisplayConnector::enable_console()
{
VERIFY(m_control_lock.is_locked());
diff --git a/Kernel/Graphics/Bochs/DisplayConnector.h b/Kernel/Graphics/Bochs/DisplayConnector.h
index 48d31e22bd..445e5dcc7c 100644
--- a/Kernel/Graphics/Bochs/DisplayConnector.h
+++ b/Kernel/Graphics/Bochs/DisplayConnector.h
@@ -24,14 +24,14 @@ class BochsDisplayConnector
public:
TYPEDEF_DISTINCT_ORDERED_ID(u16, IndexID);
- static NonnullRefPtr<BochsDisplayConnector> must_create(PhysicalAddress framebuffer_address);
+ static NonnullRefPtr<BochsDisplayConnector> must_create(PhysicalAddress framebuffer_address, size_t framebuffer_resource_size);
virtual IndexID index_id() const;
protected:
ErrorOr<void> create_attached_framebuffer_console();
- explicit BochsDisplayConnector(PhysicalAddress framebuffer_address);
+ BochsDisplayConnector(PhysicalAddress framebuffer_address, size_t framebuffer_resource_size);
virtual bool mutable_mode_setting_capable() const override final { return true; }
virtual bool double_framebuffering_capable() const override { return false; }
@@ -45,15 +45,11 @@ protected:
// Note: Paravirtualized hardware doesn't require a defined refresh rate for modesetting.
virtual bool refresh_rate_support() const override final { return false; }
- virtual ErrorOr<size_t> write_to_first_surface(u64 offset, UserOrKernelBuffer const&, size_t length) override final;
virtual ErrorOr<void> flush_first_surface() override final;
virtual void enable_console() override final;
virtual void disable_console() override final;
- const PhysicalAddress m_framebuffer_address;
RefPtr<Graphics::GenericFramebufferConsole> m_framebuffer_console;
- OwnPtr<Memory::Region> m_framebuffer_region;
- u8* m_framebuffer_data {};
};
}
diff --git a/Kernel/Graphics/Bochs/GraphicsAdapter.cpp b/Kernel/Graphics/Bochs/GraphicsAdapter.cpp
index ed64295587..82e63686ee 100644
--- a/Kernel/Graphics/Bochs/GraphicsAdapter.cpp
+++ b/Kernel/Graphics/Bochs/GraphicsAdapter.cpp
@@ -43,13 +43,14 @@ UNMAP_AFTER_INIT ErrorOr<void> BochsGraphicsAdapter::initialize_adapter(PCI::Dev
// Note: If we use VirtualBox graphics adapter (which is based on Bochs one), we need to use IO ports
// Note: Bochs (the real bochs graphics adapter in the Bochs emulator) uses revision ID of 0x0
// and doesn't support memory-mapped IO registers.
+ auto bar0_space_size = PCI::get_BAR_space_size(pci_device_identifier.address(), 0);
if (pci_device_identifier.revision_id().value() == 0x0
|| (pci_device_identifier.hardware_id().vendor_id == 0x80ee && pci_device_identifier.hardware_id().device_id == 0xbeef)) {
- m_display_connector = BochsDisplayConnector::must_create(PhysicalAddress(PCI::get_BAR0(pci_device_identifier.address()) & 0xfffffff0));
+ m_display_connector = BochsDisplayConnector::must_create(PhysicalAddress(PCI::get_BAR0(pci_device_identifier.address()) & 0xfffffff0), bar0_space_size);
} else {
auto registers_mapping = TRY(Memory::map_typed_writable<BochsDisplayMMIORegisters volatile>(PhysicalAddress(PCI::get_BAR2(pci_device_identifier.address()) & 0xfffffff0)));
VERIFY(registers_mapping.region);
- m_display_connector = QEMUDisplayConnector::must_create(PhysicalAddress(PCI::get_BAR0(pci_device_identifier.address()) & 0xfffffff0), move(registers_mapping));
+ m_display_connector = QEMUDisplayConnector::must_create(PhysicalAddress(PCI::get_BAR0(pci_device_identifier.address()) & 0xfffffff0), bar0_space_size, move(registers_mapping));
}
// Note: According to Gerd Hoffmann - "The linux driver simply does
diff --git a/Kernel/Graphics/Bochs/QEMUDisplayConnector.cpp b/Kernel/Graphics/Bochs/QEMUDisplayConnector.cpp
index cf1f681b60..1f76222a56 100644
--- a/Kernel/Graphics/Bochs/QEMUDisplayConnector.cpp
+++ b/Kernel/Graphics/Bochs/QEMUDisplayConnector.cpp
@@ -12,9 +12,9 @@
namespace Kernel {
-NonnullRefPtr<QEMUDisplayConnector> QEMUDisplayConnector::must_create(PhysicalAddress framebuffer_address, Memory::TypedMapping<BochsDisplayMMIORegisters volatile> registers_mapping)
+NonnullRefPtr<QEMUDisplayConnector> QEMUDisplayConnector::must_create(PhysicalAddress framebuffer_address, size_t framebuffer_resource_size, Memory::TypedMapping<BochsDisplayMMIORegisters volatile> registers_mapping)
{
- auto device_or_error = DeviceManagement::try_create_device<QEMUDisplayConnector>(framebuffer_address, move(registers_mapping));
+ auto device_or_error = DeviceManagement::try_create_device<QEMUDisplayConnector>(framebuffer_address, framebuffer_resource_size, move(registers_mapping));
VERIFY(!device_or_error.is_error());
auto connector = device_or_error.release_value();
MUST(connector->create_attached_framebuffer_console());
@@ -31,8 +31,8 @@ ErrorOr<void> QEMUDisplayConnector::fetch_and_initialize_edid()
return {};
}
-QEMUDisplayConnector::QEMUDisplayConnector(PhysicalAddress framebuffer_address, Memory::TypedMapping<BochsDisplayMMIORegisters volatile> registers_mapping)
- : BochsDisplayConnector(framebuffer_address)
+QEMUDisplayConnector::QEMUDisplayConnector(PhysicalAddress framebuffer_address, size_t framebuffer_resource_size, Memory::TypedMapping<BochsDisplayMMIORegisters volatile> registers_mapping)
+ : BochsDisplayConnector(framebuffer_address, framebuffer_resource_size)
, m_registers(move(registers_mapping))
{
}
@@ -111,10 +111,7 @@ ErrorOr<void> QEMUDisplayConnector::set_mode_setting(ModeSetting const& mode_set
if ((u16)width != m_registers->bochs_regs.xres || (u16)height != m_registers->bochs_regs.yres) {
return Error::from_errno(ENOTIMPL);
}
- auto rounded_size = TRY(Memory::page_round_up(width * sizeof(u32) * height * 2));
- m_framebuffer_region = TRY(MM.allocate_kernel_region(m_framebuffer_address.page_base(), rounded_size, "Framebuffer"sv, Memory::Region::Access::ReadWrite));
- [[maybe_unused]] auto result = m_framebuffer_region->set_write_combine(true);
- m_framebuffer_data = m_framebuffer_region->vaddr().offset(m_framebuffer_address.offset_in_page()).as_ptr();
+
m_framebuffer_console->set_resolution(width, height, width * sizeof(u32));
DisplayConnector::ModeSetting mode_set {
diff --git a/Kernel/Graphics/Bochs/QEMUDisplayConnector.h b/Kernel/Graphics/Bochs/QEMUDisplayConnector.h
index 003be2af7f..9486d1e663 100644
--- a/Kernel/Graphics/Bochs/QEMUDisplayConnector.h
+++ b/Kernel/Graphics/Bochs/QEMUDisplayConnector.h
@@ -22,13 +22,13 @@ class QEMUDisplayConnector final
friend class DeviceManagement;
public:
- static NonnullRefPtr<QEMUDisplayConnector> must_create(PhysicalAddress framebuffer_address, Memory::TypedMapping<BochsDisplayMMIORegisters volatile>);
+ static NonnullRefPtr<QEMUDisplayConnector> must_create(PhysicalAddress framebuffer_address, size_t framebuffer_resource_size, Memory::TypedMapping<BochsDisplayMMIORegisters volatile>);
virtual IndexID index_id() const override;
private:
ErrorOr<void> fetch_and_initialize_edid();
- QEMUDisplayConnector(PhysicalAddress framebuffer_address, Memory::TypedMapping<BochsDisplayMMIORegisters volatile>);
+ QEMUDisplayConnector(PhysicalAddress framebuffer_address, size_t framebuffer_resource_size, Memory::TypedMapping<BochsDisplayMMIORegisters volatile>);
virtual bool double_framebuffering_capable() const override { return true; }
virtual ErrorOr<void> set_mode_setting(ModeSetting const&) override;
diff --git a/Kernel/Graphics/DisplayConnector.cpp b/Kernel/Graphics/DisplayConnector.cpp
index 77ae47e395..31ae25e0b7 100644
--- a/Kernel/Graphics/DisplayConnector.cpp
+++ b/Kernel/Graphics/DisplayConnector.cpp
@@ -6,18 +6,42 @@
#include <Kernel/Graphics/DisplayConnector.h>
#include <Kernel/Graphics/GraphicsManagement.h>
+#include <Kernel/Memory/MemoryManager.h>
#include <LibC/sys/ioctl_numbers.h>
namespace Kernel {
-DisplayConnector::DisplayConnector()
+DisplayConnector::DisplayConnector(PhysicalAddress framebuffer_address, size_t framebuffer_resource_size, bool enable_write_combine_optimization)
: CharacterDevice(226, GraphicsManagement::the().allocate_minor_device_number())
+ , m_enable_write_combine_optimization(enable_write_combine_optimization)
+ , m_framebuffer_at_arbitrary_physical_range(false)
+ , m_framebuffer_address(framebuffer_address)
+ , m_framebuffer_resource_size(framebuffer_resource_size)
{
}
-ErrorOr<Memory::Region*> DisplayConnector::mmap(Process&, OpenFileDescription&, Memory::VirtualRange const&, u64, int, bool)
+DisplayConnector::DisplayConnector(size_t framebuffer_resource_size, bool enable_write_combine_optimization)
+ : CharacterDevice(226, GraphicsManagement::the().allocate_minor_device_number())
+ , m_enable_write_combine_optimization(enable_write_combine_optimization)
+ , m_framebuffer_at_arbitrary_physical_range(true)
+ , m_framebuffer_address({})
+ , m_framebuffer_resource_size(framebuffer_resource_size)
{
- return Error::from_errno(ENOTSUP);
+}
+
+ErrorOr<Memory::Region*> DisplayConnector::mmap(Process& process, OpenFileDescription&, Memory::VirtualRange const& range, u64 offset, int prot, bool shared)
+{
+ VERIFY(m_shared_framebuffer_vmobject);
+ if (offset != 0)
+ return Error::from_errno(ENOTSUP);
+
+ return process.address_space().allocate_region_with_vmobject(
+ range,
+ *m_shared_framebuffer_vmobject,
+ 0,
+ "Mapped Framebuffer",
+ prot,
+ shared);
}
ErrorOr<size_t> DisplayConnector::read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t)
@@ -32,7 +56,10 @@ ErrorOr<size_t> DisplayConnector::write(OpenFileDescription&, u64 offset, UserOr
if (console_mode()) {
return length;
}
- return write_to_first_surface(offset, framebuffer_data, length);
+ if (offset + length > m_framebuffer_region->size())
+ return Error::from_errno(EOVERFLOW);
+ TRY(framebuffer_data.read(m_framebuffer_data + offset, 0, length));
+ return length;
}
void DisplayConnector::will_be_destroyed()
@@ -44,7 +71,24 @@ void DisplayConnector::will_be_destroyed()
void DisplayConnector::after_inserting()
{
Device::after_inserting();
+ auto rounded_size = MUST(Memory::page_round_up(m_framebuffer_resource_size));
+
+ if (!m_framebuffer_at_arbitrary_physical_range) {
+ VERIFY(m_framebuffer_address.value().page_base() == m_framebuffer_address.value());
+ m_shared_framebuffer_vmobject = MUST(Memory::SharedFramebufferVMObject::try_create_for_physical_range(m_framebuffer_address.value(), rounded_size));
+ m_framebuffer_region = MUST(MM.allocate_kernel_region(m_framebuffer_address.value().page_base(), rounded_size, "Framebuffer"sv, Memory::Region::Access::ReadWrite));
+ } else {
+ m_shared_framebuffer_vmobject = MUST(Memory::SharedFramebufferVMObject::try_create_at_arbitrary_physical_range(rounded_size));
+ m_framebuffer_region = MUST(MM.allocate_kernel_region_with_vmobject(m_shared_framebuffer_vmobject->real_writes_framebuffer_vmobject(), rounded_size, "Framebuffer"sv, Memory::Region::Access::ReadWrite));
+ }
+
+ m_framebuffer_data = m_framebuffer_region->vaddr().as_ptr();
+ m_fake_writes_framebuffer_region = MUST(MM.allocate_kernel_region_with_vmobject(m_shared_framebuffer_vmobject->fake_writes_framebuffer_vmobject(), rounded_size, "Fake Writes Framebuffer"sv, Memory::Region::Access::ReadWrite));
+
GraphicsManagement::the().attach_new_display_connector({}, *this);
+ if (m_enable_write_combine_optimization) {
+ [[maybe_unused]] auto result = m_framebuffer_region->set_write_combine(true);
+ }
}
bool DisplayConnector::console_mode() const
@@ -56,15 +100,24 @@ bool DisplayConnector::console_mode() const
void DisplayConnector::set_display_mode(Badge<GraphicsManagement>, DisplayMode mode)
{
SpinlockLocker locker(m_control_lock);
+
{
SpinlockLocker locker(m_modeset_lock);
[[maybe_unused]] auto result = set_y_offset(0);
}
+
m_console_mode = mode == DisplayMode::Console ? true : false;
- if (m_console_mode)
+ if (m_console_mode) {
+ VERIFY(m_framebuffer_region->size() == m_fake_writes_framebuffer_region->size());
+ memcpy(m_fake_writes_framebuffer_region->vaddr().as_ptr(), m_framebuffer_region->vaddr().as_ptr(), m_framebuffer_region->size());
+ m_shared_framebuffer_vmobject->switch_to_fake_sink_framebuffer_writes({});
enable_console();
- else
+ } else {
disable_console();
+ m_shared_framebuffer_vmobject->switch_to_real_framebuffer_writes({});
+ VERIFY(m_framebuffer_region->size() == m_fake_writes_framebuffer_region->size());
+ memcpy(m_framebuffer_region->vaddr().as_ptr(), m_fake_writes_framebuffer_region->vaddr().as_ptr(), m_framebuffer_region->size());
+ }
}
ErrorOr<void> DisplayConnector::initialize_edid_for_generic_monitor()
diff --git a/Kernel/Graphics/DisplayConnector.h b/Kernel/Graphics/DisplayConnector.h
index ee01d7cdf4..f817a69686 100644
--- a/Kernel/Graphics/DisplayConnector.h
+++ b/Kernel/Graphics/DisplayConnector.h
@@ -8,6 +8,7 @@
#include <AK/Types.h>
#include <Kernel/Devices/CharacterDevice.h>
+#include <Kernel/Memory/SharedFramebufferVMObject.h>
#include <LibC/sys/ioctl_numbers.h>
#include <LibEDID/EDID.h>
@@ -99,6 +100,8 @@ public:
void set_display_mode(Badge<GraphicsManagement>, DisplayMode);
+ Memory::Region const& framebuffer_region() const { return *m_framebuffer_region; }
+
protected:
void set_edid_bytes(Array<u8, 128> const& edid_bytes);
@@ -112,8 +115,8 @@ protected:
virtual ErrorOr<void> ioctl(OpenFileDescription&, unsigned request, Userspace<void*> arg) override final;
virtual StringView class_name() const override final { return "DisplayConnector"sv; }
- DisplayConnector();
- virtual ErrorOr<size_t> write_to_first_surface(u64 offset, UserOrKernelBuffer const&, size_t length) = 0;
+ DisplayConnector(PhysicalAddress framebuffer_address, size_t framebuffer_resource_size, bool enable_write_combine_optimization);
+ DisplayConnector(size_t framebuffer_resource_size, bool enable_write_combine_optimization);
virtual void enable_console() = 0;
virtual void disable_console() = 0;
virtual ErrorOr<void> flush_first_surface() = 0;
@@ -135,10 +138,30 @@ protected:
EDID::Parser::RawBytes m_edid_bytes {};
bool m_edid_valid { false };
+ u8* framebuffer_data() { return m_framebuffer_data; }
+
private:
+ DisplayConnector& operator=(DisplayConnector const&) = delete;
+ DisplayConnector& operator=(DisplayConnector&&) = delete;
+ DisplayConnector(DisplayConnector&&) = delete;
+
virtual void will_be_destroyed() override;
virtual void after_inserting() override;
+ OwnPtr<Memory::Region> m_framebuffer_region;
+ OwnPtr<Memory::Region> m_fake_writes_framebuffer_region;
+ u8* m_framebuffer_data {};
+
+ bool const m_enable_write_combine_optimization { false };
+ bool const m_framebuffer_at_arbitrary_physical_range { false };
+
+protected:
+ Optional<PhysicalAddress> const m_framebuffer_address;
+ size_t const m_framebuffer_resource_size;
+
+private:
+ RefPtr<Memory::SharedFramebufferVMObject> m_shared_framebuffer_vmobject;
+
IntrusiveListNode<DisplayConnector, RefPtr<DisplayConnector>> m_list_node;
};
}
diff --git a/Kernel/Graphics/Intel/NativeDisplayConnector.cpp b/Kernel/Graphics/Intel/NativeDisplayConnector.cpp
index 724f4c4b1a..4f4470e116 100644
--- a/Kernel/Graphics/Intel/NativeDisplayConnector.cpp
+++ b/Kernel/Graphics/Intel/NativeDisplayConnector.cpp
@@ -175,10 +175,10 @@ Optional<IntelGraphics::PLLSettings> IntelNativeDisplayConnector::create_pll_set
return {};
}
-NonnullRefPtr<IntelNativeDisplayConnector> IntelNativeDisplayConnector::must_create(PhysicalAddress framebuffer_address, PhysicalAddress registers_region_address, size_t registers_region_length)
+NonnullRefPtr<IntelNativeDisplayConnector> IntelNativeDisplayConnector::must_create(PhysicalAddress framebuffer_address, size_t framebuffer_resource_size, PhysicalAddress registers_region_address, size_t registers_region_length)
{
auto registers_region = MUST(MM.allocate_kernel_region(PhysicalAddress(registers_region_address), registers_region_length, "Intel Native Graphics Registers", Memory::Region::Access::ReadWrite));
- auto device_or_error = DeviceManagement::try_create_device<IntelNativeDisplayConnector>(framebuffer_address, move(registers_region));
+ auto device_or_error = DeviceManagement::try_create_device<IntelNativeDisplayConnector>(framebuffer_address, framebuffer_resource_size, move(registers_region));
VERIFY(!device_or_error.is_error());
auto connector = device_or_error.release_value();
MUST(connector->initialize_gmbus_settings_and_read_edid());
@@ -208,15 +208,6 @@ ErrorOr<void> IntelNativeDisplayConnector::unblank()
return Error::from_errno(ENOTIMPL);
}
-ErrorOr<size_t> IntelNativeDisplayConnector::write_to_first_surface(u64 offset, UserOrKernelBuffer const& buffer, size_t length)
-{
- VERIFY(m_control_lock.is_locked());
- if (offset + length > m_framebuffer_region->size())
- return Error::from_errno(EOVERFLOW);
- TRY(buffer.read(m_framebuffer_data + offset, 0, length));
- return length;
-}
-
void IntelNativeDisplayConnector::enable_console()
{
VERIFY(m_control_lock.is_locked());
@@ -238,19 +229,13 @@ ErrorOr<void> IntelNativeDisplayConnector::flush_first_surface()
ErrorOr<void> IntelNativeDisplayConnector::create_attached_framebuffer_console()
{
- auto rounded_size = TRY(Memory::page_round_up(m_current_mode_setting.vertical_active * m_current_mode_setting.horizontal_stride));
- m_framebuffer_region = TRY(MM.allocate_kernel_region(m_framebuffer_address.page_base(), rounded_size, "Framebuffer"sv, Memory::Region::Access::ReadWrite));
- [[maybe_unused]] auto result = m_framebuffer_region->set_write_combine(true);
- m_framebuffer_data = m_framebuffer_region->vaddr().offset(m_framebuffer_address.offset_in_page()).as_ptr();
-
- m_framebuffer_console = Graphics::ContiguousFramebufferConsole::initialize(m_framebuffer_address, m_current_mode_setting.horizontal_active, m_current_mode_setting.vertical_active, m_current_mode_setting.horizontal_stride);
+ m_framebuffer_console = Graphics::ContiguousFramebufferConsole::initialize(m_framebuffer_address.value(), m_current_mode_setting.horizontal_active, m_current_mode_setting.vertical_active, m_current_mode_setting.horizontal_stride);
GraphicsManagement::the().set_console(*m_framebuffer_console);
return {};
}
-IntelNativeDisplayConnector::IntelNativeDisplayConnector(PhysicalAddress framebuffer_address, NonnullOwnPtr<Memory::Region> registers_region)
- : DisplayConnector()
- , m_framebuffer_address(framebuffer_address)
+IntelNativeDisplayConnector::IntelNativeDisplayConnector(PhysicalAddress framebuffer_address, size_t framebuffer_resource_size, NonnullOwnPtr<Memory::Region> registers_region)
+ : DisplayConnector(framebuffer_address, framebuffer_resource_size, true)
, m_registers_region(move(registers_region))
{
{
@@ -506,7 +491,7 @@ bool IntelNativeDisplayConnector::set_safe_crt_resolution()
dbgln_if(INTEL_GRAPHICS_DEBUG, "PLL settings for {} {} {} {} {}", settings.n, settings.m1, settings.m2, settings.p1, settings.p2);
enable_dpll_without_vga(pll_settings.value(), dac_multiplier);
set_display_timings(modesetting);
- enable_output(m_framebuffer_address, modesetting.horizontal.blanking_start());
+ enable_output(m_framebuffer_address.value(), modesetting.horizontal.blanking_start());
DisplayConnector::ModeSetting mode_set {
.horizontal_stride = modesetting.horizontal.blanking_start() * sizeof(u32),
@@ -525,10 +510,6 @@ bool IntelNativeDisplayConnector::set_safe_crt_resolution()
m_current_mode_setting = mode_set;
- auto rounded_size = MUST(Memory::page_round_up(m_current_mode_setting.vertical_active * m_current_mode_setting.horizontal_stride));
- m_framebuffer_region = MUST(MM.allocate_kernel_region(m_framebuffer_address, rounded_size, "Intel Native Graphics Framebuffer", Memory::Region::Access::ReadWrite));
- m_framebuffer_data = m_framebuffer_region->vaddr().offset(m_framebuffer_address.offset_in_page()).as_ptr();
-
if (m_framebuffer_console)
m_framebuffer_console->set_resolution(m_current_mode_setting.horizontal_active, m_current_mode_setting.vertical_active, m_current_mode_setting.horizontal_stride);
diff --git a/Kernel/Graphics/Intel/NativeDisplayConnector.h b/Kernel/Graphics/Intel/NativeDisplayConnector.h
index 53598c24f1..84e2ef0dba 100644
--- a/Kernel/Graphics/Intel/NativeDisplayConnector.h
+++ b/Kernel/Graphics/Intel/NativeDisplayConnector.h
@@ -81,7 +81,7 @@ class IntelNativeDisplayConnector final
friend class DeviceManagement;
public:
- static NonnullRefPtr<IntelNativeDisplayConnector> must_create(PhysicalAddress framebuffer_address, PhysicalAddress registers_region_address, size_t registers_region_length);
+ static NonnullRefPtr<IntelNativeDisplayConnector> must_create(PhysicalAddress framebuffer_address, size_t framebuffer_resource_size, PhysicalAddress registers_region_address, size_t registers_region_length);
private:
// ^DisplayConnector
@@ -93,7 +93,6 @@ private:
virtual ErrorOr<void> set_safe_mode_setting() override;
virtual ErrorOr<void> set_y_offset(size_t y) override;
virtual ErrorOr<void> unblank() override;
- virtual ErrorOr<size_t> write_to_first_surface(u64 offset, UserOrKernelBuffer const&, size_t length) override final;
virtual ErrorOr<void> flush_first_surface() override final;
virtual void enable_console() override;
virtual void disable_console() override;
@@ -104,7 +103,7 @@ private:
ErrorOr<void> initialize_gmbus_settings_and_read_edid();
- IntelNativeDisplayConnector(PhysicalAddress framebuffer_address, NonnullOwnPtr<Memory::Region> registers_region);
+ IntelNativeDisplayConnector(PhysicalAddress framebuffer_address, size_t framebuffer_resource_size, NonnullOwnPtr<Memory::Region> registers_region);
ErrorOr<void> create_attached_framebuffer_console();
@@ -156,10 +155,7 @@ private:
Optional<IntelGraphics::PLLSettings> create_pll_settings(u64 target_frequency, u64 reference_clock, IntelGraphics::PLLMaxSettings const&);
mutable Spinlock m_registers_lock;
- const PhysicalAddress m_framebuffer_address;
RefPtr<Graphics::GenericFramebufferConsole> m_framebuffer_console;
- OwnPtr<Memory::Region> m_framebuffer_region;
- u8* m_framebuffer_data {};
const PhysicalAddress m_registers;
NonnullOwnPtr<Memory::Region> m_registers_region;
diff --git a/Kernel/Graphics/Intel/NativeGraphicsAdapter.cpp b/Kernel/Graphics/Intel/NativeGraphicsAdapter.cpp
index d9bbd29bf4..f5e14989f4 100644
--- a/Kernel/Graphics/Intel/NativeGraphicsAdapter.cpp
+++ b/Kernel/Graphics/Intel/NativeGraphicsAdapter.cpp
@@ -43,11 +43,12 @@ ErrorOr<void> IntelNativeGraphicsAdapter::initialize_adapter()
dbgln_if(INTEL_GRAPHICS_DEBUG, "Intel Native Graphics Adapter @ {}", address);
auto bar0_space_size = PCI::get_BAR_space_size(address, 0);
VERIFY(bar0_space_size == 0x80000);
+ auto bar2_space_size = PCI::get_BAR_space_size(address, 2);
dmesgln("Intel Native Graphics Adapter @ {}, MMIO @ {}, space size is {:x} bytes", address, PhysicalAddress(PCI::get_BAR0(address)), bar0_space_size);
dmesgln("Intel Native Graphics Adapter @ {}, framebuffer @ {}", address, PhysicalAddress(PCI::get_BAR2(address)));
PCI::enable_bus_mastering(address);
- m_display_connector = IntelNativeDisplayConnector::must_create(PhysicalAddress(PCI::get_BAR2(address) & 0xfffffff0), PhysicalAddress(PCI::get_BAR0(address) & 0xfffffff0), bar0_space_size);
+ m_display_connector = IntelNativeDisplayConnector::must_create(PhysicalAddress(PCI::get_BAR2(address) & 0xfffffff0), bar2_space_size, PhysicalAddress(PCI::get_BAR0(address) & 0xfffffff0), bar0_space_size);
return {};
}
diff --git a/Kernel/Graphics/VGA/DisplayConnector.cpp b/Kernel/Graphics/VGA/DisplayConnector.cpp
index c83f3fbc4c..da3ce993b2 100644
--- a/Kernel/Graphics/VGA/DisplayConnector.cpp
+++ b/Kernel/Graphics/VGA/DisplayConnector.cpp
@@ -24,8 +24,7 @@ NonnullRefPtr<GenericDisplayConnector> GenericDisplayConnector::must_create_with
}
GenericDisplayConnector::GenericDisplayConnector(PhysicalAddress framebuffer_address, size_t width, size_t height, size_t pitch)
- : DisplayConnector()
- , m_framebuffer_address(framebuffer_address)
+ : DisplayConnector(framebuffer_address, height * pitch, true)
{
m_current_mode_setting.horizontal_active = width;
m_current_mode_setting.vertical_active = height;
@@ -38,24 +37,11 @@ ErrorOr<void> GenericDisplayConnector::create_attached_framebuffer_console()
auto height = m_current_mode_setting.vertical_active;
auto pitch = m_current_mode_setting.horizontal_stride;
- auto rounded_size = TRY(Memory::page_round_up(pitch * height));
- m_framebuffer_region = TRY(MM.allocate_kernel_region(m_framebuffer_address.page_base(), rounded_size, "Framebuffer"sv, Memory::Region::Access::ReadWrite));
- [[maybe_unused]] auto result = m_framebuffer_region->set_write_combine(true);
- m_framebuffer_data = m_framebuffer_region->vaddr().offset(m_framebuffer_address.offset_in_page()).as_ptr();
- m_framebuffer_console = Graphics::ContiguousFramebufferConsole::initialize(m_framebuffer_address, width, height, pitch);
+ m_framebuffer_console = Graphics::ContiguousFramebufferConsole::initialize(m_framebuffer_address.value(), width, height, pitch);
GraphicsManagement::the().set_console(*m_framebuffer_console);
return {};
}
-ErrorOr<size_t> GenericDisplayConnector::write_to_first_surface(u64 offset, UserOrKernelBuffer const& buffer, size_t length)
-{
- VERIFY(m_control_lock.is_locked());
- if (offset + length > m_framebuffer_region->size())
- return Error::from_errno(EOVERFLOW);
- TRY(buffer.read(m_framebuffer_data + offset, 0, length));
- return length;
-}
-
void GenericDisplayConnector::enable_console()
{
VERIFY(m_control_lock.is_locked());
diff --git a/Kernel/Graphics/VGA/DisplayConnector.h b/Kernel/Graphics/VGA/DisplayConnector.h
index e2c7a7e3f6..ac48386f2c 100644
--- a/Kernel/Graphics/VGA/DisplayConnector.h
+++ b/Kernel/Graphics/VGA/DisplayConnector.h
@@ -39,15 +39,11 @@ protected:
// Note: This is possibly a paravirtualized hardware, but since we don't know, we assume there's no refresh rate...
virtual bool refresh_rate_support() const override final { return false; }
- virtual ErrorOr<size_t> write_to_first_surface(u64 offset, UserOrKernelBuffer const&, size_t length) override final;
virtual ErrorOr<void> flush_first_surface() override final;
virtual void enable_console() override final;
virtual void disable_console() override final;
- const PhysicalAddress m_framebuffer_address;
RefPtr<Graphics::GenericFramebufferConsole> m_framebuffer_console;
- OwnPtr<Memory::Region> m_framebuffer_region;
- u8* m_framebuffer_data {};
};
}
diff --git a/Kernel/Graphics/VMWare/DisplayConnector.cpp b/Kernel/Graphics/VMWare/DisplayConnector.cpp
index a5ee870de4..a50d22ebcf 100644
--- a/Kernel/Graphics/VMWare/DisplayConnector.cpp
+++ b/Kernel/Graphics/VMWare/DisplayConnector.cpp
@@ -12,9 +12,9 @@
namespace Kernel {
-NonnullRefPtr<VMWareDisplayConnector> VMWareDisplayConnector::must_create(VMWareGraphicsAdapter const& parent_adapter, PhysicalAddress framebuffer_address)
+NonnullRefPtr<VMWareDisplayConnector> VMWareDisplayConnector::must_create(VMWareGraphicsAdapter const& parent_adapter, PhysicalAddress framebuffer_address, size_t framebuffer_resource_size)
{
- auto connector = MUST(DeviceManagement::try_create_device<VMWareDisplayConnector>(parent_adapter, framebuffer_address));
+ auto connector = MUST(DeviceManagement::try_create_device<VMWareDisplayConnector>(parent_adapter, framebuffer_address, framebuffer_resource_size));
MUST(connector->create_attached_framebuffer_console());
MUST(connector->initialize_edid_for_generic_monitor());
return connector;
@@ -22,18 +22,13 @@ NonnullRefPtr<VMWareDisplayConnector> VMWareDisplayConnector::must_create(VMWare
ErrorOr<void> VMWareDisplayConnector::create_attached_framebuffer_console()
{
- auto rounded_size = TRY(Memory::page_round_up(1024 * sizeof(u32) * 768));
- m_framebuffer_region = TRY(MM.allocate_kernel_region(m_framebuffer_address.page_base(), rounded_size, "Framebuffer"sv, Memory::Region::Access::ReadWrite));
- [[maybe_unused]] auto result = m_framebuffer_region->set_write_combine(true);
- m_framebuffer_data = m_framebuffer_region->vaddr().offset(m_framebuffer_address.offset_in_page()).as_ptr();
m_framebuffer_console = VMWareFramebufferConsole::initialize(*this);
GraphicsManagement::the().set_console(*m_framebuffer_console);
return {};
}
-VMWareDisplayConnector::VMWareDisplayConnector(VMWareGraphicsAdapter const& parent_adapter, PhysicalAddress framebuffer_address)
- : DisplayConnector()
- , m_framebuffer_address(framebuffer_address)
+VMWareDisplayConnector::VMWareDisplayConnector(VMWareGraphicsAdapter const& parent_adapter, PhysicalAddress framebuffer_address, size_t framebuffer_resource_size)
+ : DisplayConnector(framebuffer_address, framebuffer_resource_size, false)
, m_parent_adapter(parent_adapter)
{
}
@@ -63,15 +58,6 @@ ErrorOr<void> VMWareDisplayConnector::unblank()
return Error::from_errno(ENOTIMPL);
}
-ErrorOr<size_t> VMWareDisplayConnector::write_to_first_surface(u64 offset, UserOrKernelBuffer const& buffer, size_t length)
-{
- VERIFY(m_control_lock.is_locked());
- if (offset + length > m_framebuffer_region->size())
- return Error::from_errno(EOVERFLOW);
- TRY(buffer.read(m_framebuffer_data + offset, 0, length));
- return length;
-}
-
void VMWareDisplayConnector::enable_console()
{
VERIFY(m_control_lock.is_locked());
@@ -124,10 +110,6 @@ ErrorOr<void> VMWareDisplayConnector::set_mode_setting(ModeSetting const& mode_s
TRY(m_parent_adapter->modeset_primary_screen_resolution({}, width, height));
- auto rounded_size = TRY(Memory::page_round_up(width * sizeof(u32) * height));
- m_framebuffer_region = TRY(MM.allocate_kernel_region(m_framebuffer_address.page_base(), rounded_size, "Framebuffer"sv, Memory::Region::Access::ReadWrite));
- [[maybe_unused]] auto result = m_framebuffer_region->set_write_combine(true);
- m_framebuffer_data = m_framebuffer_region->vaddr().offset(m_framebuffer_address.offset_in_page()).as_ptr();
m_framebuffer_console->set_resolution(width, height, width * sizeof(u32));
auto pitch = m_parent_adapter->primary_screen_pitch({});
diff --git a/Kernel/Graphics/VMWare/DisplayConnector.h b/Kernel/Graphics/VMWare/DisplayConnector.h
index d17e51b8e3..6f60653fd1 100644
--- a/Kernel/Graphics/VMWare/DisplayConnector.h
+++ b/Kernel/Graphics/VMWare/DisplayConnector.h
@@ -23,10 +23,10 @@ class VMWareDisplayConnector : public DisplayConnector {
friend class DeviceManagement;
public:
- static NonnullRefPtr<VMWareDisplayConnector> must_create(VMWareGraphicsAdapter const& parent_adapter, PhysicalAddress framebuffer_address);
+ static NonnullRefPtr<VMWareDisplayConnector> must_create(VMWareGraphicsAdapter const& parent_adapter, PhysicalAddress framebuffer_address, size_t framebuffer_resource_size);
private:
- VMWareDisplayConnector(VMWareGraphicsAdapter const& parent_adapter, PhysicalAddress framebuffer_address);
+ VMWareDisplayConnector(VMWareGraphicsAdapter const& parent_adapter, PhysicalAddress framebuffer_address, size_t framebuffer_resource_size);
ErrorOr<void> create_attached_framebuffer_console();
virtual bool mutable_mode_setting_capable() const override { return true; }
@@ -41,7 +41,6 @@ private:
// Note: Paravirtualized hardware doesn't require a defined refresh rate for modesetting.
virtual bool refresh_rate_support() const override { return false; }
- virtual ErrorOr<size_t> write_to_first_surface(u64 offset, UserOrKernelBuffer const&, size_t length) override;
virtual ErrorOr<void> flush_first_surface() override;
virtual ErrorOr<void> flush_rectangle(size_t buffer_index, FBRect const& rect) override;
@@ -49,12 +48,7 @@ private:
virtual void disable_console() override;
private:
- u8* framebuffer_data() { return m_framebuffer_data; }
-
- const PhysicalAddress m_framebuffer_address;
NonnullRefPtr<VMWareGraphicsAdapter> m_parent_adapter;
RefPtr<VMWareFramebufferConsole> m_framebuffer_console;
- OwnPtr<Memory::Region> m_framebuffer_region;
- u8* m_framebuffer_data {};
};
}
diff --git a/Kernel/Graphics/VMWare/GraphicsAdapter.cpp b/Kernel/Graphics/VMWare/GraphicsAdapter.cpp
index debea6043e..29ad1c1adb 100644
--- a/Kernel/Graphics/VMWare/GraphicsAdapter.cpp
+++ b/Kernel/Graphics/VMWare/GraphicsAdapter.cpp
@@ -181,7 +181,9 @@ UNMAP_AFTER_INIT ErrorOr<void> VMWareGraphicsAdapter::initialize_adapter()
// Note: enable the device by modesetting the primary screen resolution
modeset_primary_screen_resolution(640, 480);
- m_display_connector = VMWareDisplayConnector::must_create(*this, PhysicalAddress(PCI::get_BAR1(pci_address()) & 0xfffffff0));
+ auto bar1_space_size = PCI::get_BAR_space_size(pci_address(), 1);
+
+ m_display_connector = VMWareDisplayConnector::must_create(*this, PhysicalAddress(PCI::get_BAR1(pci_address()) & 0xfffffff0), bar1_space_size);
TRY(m_display_connector->set_safe_mode_setting());
return {};
}
diff --git a/Kernel/Graphics/VirtIOGPU/DisplayConnector.cpp b/Kernel/Graphics/VirtIOGPU/DisplayConnector.cpp
index c9086f92ec..e7f8fe2671 100644
--- a/Kernel/Graphics/VirtIOGPU/DisplayConnector.cpp
+++ b/Kernel/Graphics/VirtIOGPU/DisplayConnector.cpp
@@ -24,8 +24,10 @@ NonnullRefPtr<VirtIODisplayConnector> VirtIODisplayConnector::must_create(VirtIO
return connector;
}
+static_assert((MAX_VIRTIOGPU_RESOLUTION_WIDTH * MAX_VIRTIOGPU_RESOLUTION_HEIGHT * sizeof(u32) * 2) % PAGE_SIZE == 0);
+
VirtIODisplayConnector::VirtIODisplayConnector(VirtIOGraphicsAdapter& graphics_adapter, Graphics::VirtIOGPU::ScanoutID scanout_id)
- : DisplayConnector()
+ : DisplayConnector((MAX_VIRTIOGPU_RESOLUTION_WIDTH * MAX_VIRTIOGPU_RESOLUTION_HEIGHT * sizeof(u32) * 2), false)
, m_graphics_adapter(graphics_adapter)
, m_scanout_id(scanout_id)
{
@@ -48,14 +50,14 @@ ErrorOr<void> VirtIODisplayConnector::set_mode_setting(ModeSetting const& mode_s
return Error::from_errno(ENOTSUP);
auto& info = m_display_info;
-
info.rect = {
.x = 0,
.y = 0,
.width = (u32)mode_setting.horizontal_active,
.height = (u32)mode_setting.vertical_active,
};
- TRY(create_framebuffer());
+
+ TRY(m_graphics_adapter->mode_set_resolution({}, *this, mode_setting.horizontal_active, mode_setting.vertical_active));
DisplayConnector::ModeSetting mode_set {
.horizontal_stride = info.rect.width * sizeof(u32),
.pixel_clock_in_khz = 0, // Note: There's no pixel clock in paravirtualized hardware
@@ -71,6 +73,8 @@ ErrorOr<void> VirtIODisplayConnector::set_mode_setting(ModeSetting const& mode_s
.vertical_offset = 0,
};
m_current_mode_setting = mode_set;
+
+ m_display_info.enabled = 1;
return {};
}
ErrorOr<void> VirtIODisplayConnector::set_safe_mode_setting()
@@ -96,9 +100,9 @@ ErrorOr<void> VirtIODisplayConnector::set_y_offset(size_t y)
{
VERIFY(m_control_lock.is_locked());
if (y == 0)
- m_current_buffer = &m_main_buffer;
+ m_last_set_buffer_index.store(0);
else if (y == m_display_info.rect.height)
- m_current_buffer = &m_back_buffer;
+ m_last_set_buffer_index.store(1);
else
return Error::from_errno(EINVAL);
return {};
@@ -108,25 +112,11 @@ ErrorOr<void> VirtIODisplayConnector::unblank()
return Error::from_errno(ENOTIMPL);
}
-ErrorOr<size_t> VirtIODisplayConnector::write_to_first_surface(u64 offset, UserOrKernelBuffer const& buffer, size_t length)
-{
- VERIFY(m_control_lock.is_locked());
- if (offset + length > (m_buffer_size * 2))
- return Error::from_errno(EOVERFLOW);
- if (offset < m_buffer_size && (offset + length) > (m_buffer_size))
- return Error::from_errno(EOVERFLOW);
- if (offset < m_buffer_size) {
- TRY(buffer.read(m_main_buffer.framebuffer_data + offset, 0, length));
- } else {
- TRY(buffer.read(m_back_buffer.framebuffer_data + offset - m_buffer_size, 0, length));
- }
-
- return length;
-}
-
ErrorOr<void> VirtIODisplayConnector::flush_rectangle(size_t buffer_index, FBRect const& rect)
{
VERIFY(m_flushing_lock.is_locked());
+ if (!is_valid_buffer_index(buffer_index))
+ return Error::from_errno(EINVAL);
SpinlockLocker locker(m_graphics_adapter->operation_lock());
Graphics::VirtIOGPU::Protocol::Rect dirty_rect {
.x = rect.x,
@@ -135,23 +125,13 @@ ErrorOr<void> VirtIODisplayConnector::flush_rectangle(size_t buffer_index, FBRec
.height = rect.height
};
- auto& buffer = buffer_from_index(buffer_index);
- transfer_framebuffer_data_to_host(dirty_rect, buffer);
- if (&buffer == m_current_buffer) {
+ bool main_buffer = (buffer_index == 0);
+ m_graphics_adapter->transfer_framebuffer_data_to_host({}, *this, dirty_rect, main_buffer);
+ if (m_last_set_buffer_index.load() == buffer_index) {
// Flushing directly to screen
- flush_displayed_image(dirty_rect, buffer);
- buffer.dirty_rect = {};
+ flush_displayed_image(dirty_rect, main_buffer);
} else {
- if (buffer.dirty_rect.width == 0 || buffer.dirty_rect.height == 0) {
- buffer.dirty_rect = dirty_rect;
- } else {
- auto current_dirty_right = buffer.dirty_rect.x + buffer.dirty_rect.width;
- auto current_dirty_bottom = buffer.dirty_rect.y + buffer.dirty_rect.height;
- buffer.dirty_rect.x = min(buffer.dirty_rect.x, dirty_rect.x);
- buffer.dirty_rect.y = min(buffer.dirty_rect.y, dirty_rect.y);
- buffer.dirty_rect.width = max(current_dirty_right, dirty_rect.x + dirty_rect.width) - buffer.dirty_rect.x;
- buffer.dirty_rect.height = max(current_dirty_bottom, dirty_rect.y + dirty_rect.height) - buffer.dirty_rect.y;
- }
+ set_dirty_displayed_rect(dirty_rect, main_buffer);
}
return {};
}
@@ -166,24 +146,14 @@ ErrorOr<void> VirtIODisplayConnector::flush_first_surface()
.width = m_display_info.rect.width,
.height = m_display_info.rect.height
};
- auto& buffer = buffer_from_index(0);
- transfer_framebuffer_data_to_host(dirty_rect, buffer);
- if (&buffer == m_current_buffer) {
- // Flushing directly to screen
- flush_displayed_image(dirty_rect, buffer);
- buffer.dirty_rect = {};
- } else {
- if (buffer.dirty_rect.width == 0 || buffer.dirty_rect.height == 0) {
- buffer.dirty_rect = dirty_rect;
- } else {
- auto current_dirty_right = buffer.dirty_rect.x + buffer.dirty_rect.width;
- auto current_dirty_bottom = buffer.dirty_rect.y + buffer.dirty_rect.height;
- buffer.dirty_rect.x = min(buffer.dirty_rect.x, dirty_rect.x);
- buffer.dirty_rect.y = min(buffer.dirty_rect.y, dirty_rect.y);
- buffer.dirty_rect.width = max(current_dirty_right, dirty_rect.x + dirty_rect.width) - buffer.dirty_rect.x;
- buffer.dirty_rect.height = max(current_dirty_bottom, dirty_rect.y + dirty_rect.height) - buffer.dirty_rect.y;
- }
- }
+
+ auto current_buffer_index = m_last_set_buffer_index.load();
+ VERIFY(is_valid_buffer_index(current_buffer_index));
+
+ bool main_buffer = (current_buffer_index == 0);
+ m_graphics_adapter->transfer_framebuffer_data_to_host({}, *this, dirty_rect, main_buffer);
+ // Flushing directly to screen
+ flush_displayed_image(dirty_rect, main_buffer);
return {};
}
@@ -201,11 +171,21 @@ void VirtIODisplayConnector::disable_console()
m_console->disable();
}
-void VirtIODisplayConnector::clear_to_black(Buffer& buffer)
+void VirtIODisplayConnector::set_edid_bytes(Badge<VirtIOGraphicsAdapter>, Array<u8, 128> const& edid_bytes)
+{
+ DisplayConnector::set_edid_bytes(edid_bytes);
+}
+
+Graphics::VirtIOGPU::Protocol::DisplayInfoResponse::Display VirtIODisplayConnector::display_information(Badge<VirtIOGraphicsAdapter>) const
+{
+ return m_display_info;
+}
+
+void VirtIODisplayConnector::clear_to_black()
{
size_t width = m_display_info.rect.width;
size_t height = m_display_info.rect.height;
- u8* data = buffer.framebuffer_data;
+ u8* data = framebuffer_data();
for (size_t i = 0; i < width * height; ++i) {
data[4 * i + 0] = 0x00;
data[4 * i + 1] = 0x00;
@@ -214,7 +194,7 @@ void VirtIODisplayConnector::clear_to_black(Buffer& buffer)
}
}
-void VirtIODisplayConnector::draw_ntsc_test_pattern(Buffer& buffer)
+void VirtIODisplayConnector::draw_ntsc_test_pattern(Badge<VirtIOGraphicsAdapter>)
{
constexpr u8 colors[12][4] = {
{ 0xff, 0xff, 0xff, 0xff }, // White
@@ -232,134 +212,57 @@ void VirtIODisplayConnector::draw_ntsc_test_pattern(Buffer& buffer)
};
size_t width = m_display_info.rect.width;
size_t height = m_display_info.rect.height;
- u8* data = buffer.framebuffer_data;
+ u8* data = framebuffer_data();
// Draw NTSC test card
- for (size_t y = 0; y < height; ++y) {
- for (size_t x = 0; x < width; ++x) {
- size_t color = 0;
- if (3 * y < 2 * height) {
- // Top 2/3 of image is 7 vertical stripes of color spectrum
- color = (7 * x) / width;
- } else if (4 * y < 3 * height) {
- // 2/3 mark to 3/4 mark is backwards color spectrum alternating with black
- auto segment = (7 * x) / width;
- color = segment % 2 ? 10 : 6 - segment;
- } else {
- if (28 * x < 5 * width) {
- color = 8;
- } else if (28 * x < 10 * width) {
- color = 0;
- } else if (28 * x < 15 * width) {
- color = 7;
- } else if (28 * x < 20 * width) {
- color = 10;
- } else if (7 * x < 6 * width) {
- // Grayscale gradient
- color = 26 - ((21 * x) / width);
+ for (size_t i = 0; i < 2; ++i) {
+ for (size_t y = 0; y < height; ++y) {
+ for (size_t x = 0; x < width; ++x) {
+ size_t color = 0;
+ if (3 * y < 2 * height) {
+ // Top 2/3 of image is 7 vertical stripes of color spectrum
+ color = (7 * x) / width;
+ } else if (4 * y < 3 * height) {
+ // 2/3 mark to 3/4 mark is backwards color spectrum alternating with black
+ auto segment = (7 * x) / width;
+ color = segment % 2 ? 10 : 6 - segment;
} else {
- // Solid black
- color = 10;
+ if (28 * x < 5 * width) {
+ color = 8;
+ } else if (28 * x < 10 * width) {
+ color = 0;
+ } else if (28 * x < 15 * width) {
+ color = 7;
+ } else if (28 * x < 20 * width) {
+ color = 10;
+ } else if (7 * x < 6 * width) {
+ // Grayscale gradient
+ color = 26 - ((21 * x) / width);
+ } else {
+ // Solid black
+ color = 10;
+ }
+ }
+ u8* pixel = &data[4 * (y * width + x)];
+ for (int i = 0; i < 4; ++i) {
+ pixel[i] = colors[color][i];
}
- }
- u8* pixel = &data[4 * (y * width + x)];
- for (int i = 0; i < 4; ++i) {
- pixel[i] = colors[color][i];
}
}
+ data = data + (width * height * sizeof(u32));
}
dbgln_if(VIRTIO_DEBUG, "Finish drawing the pattern");
}
-u8* VirtIODisplayConnector::framebuffer_data()
-{
- return m_current_buffer->framebuffer_data;
-}
-
-ErrorOr<void> VirtIODisplayConnector::create_framebuffer()
-{
- SpinlockLocker locker(m_graphics_adapter->operation_lock());
- // First delete any existing framebuffers to free the memory first
- m_framebuffer = nullptr;
- m_framebuffer_sink_vmobject = nullptr;
-
- // Allocate frame buffer for both front and back
- m_buffer_size = calculate_framebuffer_size(m_display_info.rect.width, m_display_info.rect.height);
- auto region_name = TRY(KString::formatted("VirtGPU FrameBuffer #{}", m_scanout_id.value()));
- m_framebuffer = TRY(MM.allocate_kernel_region(m_buffer_size * 2, region_name->view(), Memory::Region::Access::ReadWrite, AllocationStrategy::AllocateNow));
- auto write_sink_page = TRY(MM.allocate_user_physical_page(Memory::MemoryManager::ShouldZeroFill::No));
- auto num_needed_pages = m_framebuffer->vmobject().page_count();
-
- NonnullRefPtrVector<Memory::PhysicalPage> pages;
- for (auto i = 0u; i < num_needed_pages; ++i) {
- TRY(pages.try_append(write_sink_page));
- }
- m_framebuffer_sink_vmobject = TRY(Memory::AnonymousVMObject::try_create_with_physical_pages(pages.span()));
-
- m_current_buffer = &buffer_from_index(m_last_set_buffer_index.load());
- create_buffer(m_main_buffer, 0, m_buffer_size);
- create_buffer(m_back_buffer, m_buffer_size, m_buffer_size);
-
- return {};
-}
-
-void VirtIODisplayConnector::set_edid_bytes(Badge<VirtIOGraphicsAdapter>, Array<u8, 128> const& edid_bytes)
-{
- DisplayConnector::set_edid_bytes(edid_bytes);
-}
-
-Graphics::VirtIOGPU::Protocol::DisplayInfoResponse::Display VirtIODisplayConnector::display_information(Badge<VirtIOGraphicsAdapter>)
-{
- return m_display_info;
-}
-
-void VirtIODisplayConnector::create_buffer(Buffer& buffer, size_t framebuffer_offset, size_t framebuffer_size)
+void VirtIODisplayConnector::flush_displayed_image(Graphics::VirtIOGPU::Protocol::Rect const& dirty_rect, bool main_buffer)
{
VERIFY(m_graphics_adapter->operation_lock().is_locked());
- buffer.framebuffer_offset = framebuffer_offset;
- buffer.framebuffer_data = m_framebuffer->vaddr().as_ptr() + framebuffer_offset;
-
- // 1. Create BUFFER using VIRTIO_GPU_CMD_RESOURCE_CREATE_2D
- if (buffer.resource_id.value() != 0)
- m_graphics_adapter->delete_resource(buffer.resource_id);
- buffer.resource_id = m_graphics_adapter->create_2d_resource(m_display_info.rect);
-
- // 2. Attach backing storage using VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING
- m_graphics_adapter->ensure_backing_storage(buffer.resource_id, *m_framebuffer, buffer.framebuffer_offset, framebuffer_size);
- // 3. Use VIRTIO_GPU_CMD_SET_SCANOUT to link the framebuffer to a display scanout.
- if (&buffer == m_current_buffer)
- m_graphics_adapter->set_scanout_resource(m_scanout_id, buffer.resource_id, m_display_info.rect);
- // 4. Render our test pattern
- draw_ntsc_test_pattern(buffer);
- // 5. Use VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D to update the host resource from guest memory.
- transfer_framebuffer_data_to_host(m_display_info.rect, buffer);
- // 6. Use VIRTIO_GPU_CMD_RESOURCE_FLUSH to flush the updated resource to the display.
- if (&buffer == m_current_buffer)
- flush_displayed_image(m_display_info.rect, buffer);
-
- // Make sure we constrain the existing dirty rect (if any)
- if (buffer.dirty_rect.width != 0 || buffer.dirty_rect.height != 0) {
- auto dirty_right = buffer.dirty_rect.x + buffer.dirty_rect.width;
- auto dirty_bottom = buffer.dirty_rect.y + buffer.dirty_rect.height;
- buffer.dirty_rect.width = min(dirty_right, m_display_info.rect.x + m_display_info.rect.width) - buffer.dirty_rect.x;
- buffer.dirty_rect.height = min(dirty_bottom, m_display_info.rect.y + m_display_info.rect.height) - buffer.dirty_rect.y;
- }
-
- m_display_info.enabled = 1;
-}
-
-void VirtIODisplayConnector::transfer_framebuffer_data_to_host(Graphics::VirtIOGPU::Protocol::Rect const& rect, Buffer& buffer)
-{
- m_graphics_adapter->transfer_framebuffer_data_to_host(m_scanout_id, buffer.resource_id, rect);
+ m_graphics_adapter->flush_displayed_image({}, *this, dirty_rect, main_buffer);
}
-void VirtIODisplayConnector::flush_dirty_window(Graphics::VirtIOGPU::Protocol::Rect const& dirty_rect, Buffer& buffer)
+void VirtIODisplayConnector::set_dirty_displayed_rect(Graphics::VirtIOGPU::Protocol::Rect const& dirty_rect, bool main_buffer)
{
- m_graphics_adapter->flush_dirty_rectangle(m_scanout_id, buffer.resource_id, dirty_rect);
-}
-
-void VirtIODisplayConnector::flush_displayed_image(Graphics::VirtIOGPU::Protocol::Rect const& dirty_rect, Buffer& buffer)
-{
- m_graphics_adapter->flush_displayed_image(buffer.resource_id, dirty_rect);
+ VERIFY(m_graphics_adapter->operation_lock().is_locked());
+ m_graphics_adapter->set_dirty_displayed_rect({}, *this, dirty_rect, main_buffer);
}
}
diff --git a/Kernel/Graphics/VirtIOGPU/DisplayConnector.h b/Kernel/Graphics/VirtIOGPU/DisplayConnector.h
index 1a3b462b63..0584df94a7 100644
--- a/Kernel/Graphics/VirtIOGPU/DisplayConnector.h
+++ b/Kernel/Graphics/VirtIOGPU/DisplayConnector.h
@@ -29,20 +29,15 @@ class VirtIODisplayConnector final : public DisplayConnector {
friend class Graphics::VirtIOGPU::Console;
friend class DeviceManagement;
-private:
- struct Buffer {
- size_t framebuffer_offset { 0 };
- u8* framebuffer_data { nullptr };
- Graphics::VirtIOGPU::Protocol::Rect dirty_rect {};
- Graphics::VirtIOGPU::ResourceID resource_id { 0 };
- };
-
public:
static NonnullRefPtr<VirtIODisplayConnector> must_create(VirtIOGraphicsAdapter& graphics_adapter, Graphics::VirtIOGPU::ScanoutID scanout_id);
void set_edid_bytes(Badge<VirtIOGraphicsAdapter>, Array<u8, 128> const& edid_bytes);
void set_safe_mode_setting_after_initialization(Badge<VirtIOGraphicsAdapter>);
- Graphics::VirtIOGPU::Protocol::DisplayInfoResponse::Display display_information(Badge<VirtIOGraphicsAdapter>);
+ Graphics::VirtIOGPU::ScanoutID scanout_id() const { return m_scanout_id; }
+ Graphics::VirtIOGPU::Protocol::DisplayInfoResponse::Display display_information(Badge<VirtIOGraphicsAdapter>) const;
+
+ void draw_ntsc_test_pattern(Badge<VirtIOGraphicsAdapter>);
private:
void initialize_console();
@@ -59,45 +54,28 @@ private:
// Note: Paravirtualized hardware doesn't require a defined refresh rate for modesetting.
virtual bool refresh_rate_support() const override { return false; }
- virtual ErrorOr<size_t> write_to_first_surface(u64 offset, UserOrKernelBuffer const&, size_t length) override;
virtual ErrorOr<void> flush_first_surface() override;
virtual ErrorOr<void> flush_rectangle(size_t buffer_index, FBRect const& rect) override;
virtual void enable_console() override;
virtual void disable_console() override;
+ static bool is_valid_buffer_index(size_t buffer_index)
+ {
+ return buffer_index == 0 || buffer_index == 1;
+ }
+
private:
VirtIODisplayConnector(VirtIOGraphicsAdapter& graphics_adapter, Graphics::VirtIOGPU::ScanoutID scanout_id);
+ void flush_displayed_image(Graphics::VirtIOGPU::Protocol::Rect const& dirty_rect, bool main_buffer);
+ void set_dirty_displayed_rect(Graphics::VirtIOGPU::Protocol::Rect const& dirty_rect, bool main_buffer);
+
void query_display_information();
ErrorOr<void> query_edid_from_virtio_adapter();
void query_display_edid();
- void flush_dirty_window(Graphics::VirtIOGPU::Protocol::Rect const&, Buffer&);
- void transfer_framebuffer_data_to_host(Graphics::VirtIOGPU::Protocol::Rect const&, Buffer&);
- void flush_displayed_image(Graphics::VirtIOGPU::Protocol::Rect const&, Buffer&);
-
- // Basic 2D framebuffer methods
- static size_t calculate_framebuffer_size(size_t width, size_t height)
- {
- // VirtIO resources can only map on page boundaries!
- return Memory::page_round_up(sizeof(u32) * width * height).value();
- }
- u8* framebuffer_data();
- void draw_ntsc_test_pattern(Buffer&);
- void clear_to_black(Buffer&);
- ErrorOr<void> create_framebuffer();
- void create_buffer(Buffer&, size_t, size_t);
- void set_buffer(int);
- static bool is_valid_buffer_index(int buffer_index)
- {
- return buffer_index == 0 || buffer_index == 1;
- }
- Buffer& buffer_from_index(int buffer_index)
- {
- return buffer_index == 0 ? m_main_buffer : m_back_buffer;
- }
- Buffer& current_buffer() const { return *m_current_buffer; }
+ void clear_to_black();
// Member data
// Context used for kernel operations (e.g. flushing resources to scanout)
@@ -109,13 +87,7 @@ private:
Graphics::VirtIOGPU::ScanoutID m_scanout_id;
// 2D framebuffer Member data
- size_t m_buffer_size { 0 };
- Buffer* m_current_buffer { nullptr };
- Atomic<int, AK::memory_order_relaxed> m_last_set_buffer_index { 0 };
- Buffer m_main_buffer;
- Buffer m_back_buffer;
- OwnPtr<Memory::Region> m_framebuffer;
- RefPtr<Memory::VMObject> m_framebuffer_sink_vmobject;
+ Atomic<size_t, AK::memory_order_relaxed> m_last_set_buffer_index { 0 };
constexpr static size_t NUM_TRANSFER_REGION_PAGES = 256;
};
diff --git a/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp b/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp
index 1748304484..9fb1083164 100644
--- a/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp
+++ b/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp
@@ -48,6 +48,83 @@ ErrorOr<void> VirtIOGraphicsAdapter::initialize_adapter()
return {};
}
+ErrorOr<void> VirtIOGraphicsAdapter::mode_set_resolution(Badge<VirtIODisplayConnector>, VirtIODisplayConnector& connector, size_t width, size_t height)
+{
+ SpinlockLocker locker(m_operation_lock);
+ VERIFY(connector.scanout_id() < VIRTIO_GPU_MAX_SCANOUTS);
+ auto rounded_buffer_size = TRY(calculate_framebuffer_size(width, height));
+ TRY(attach_physical_range_to_framebuffer(connector, true, 0, rounded_buffer_size));
+ TRY(attach_physical_range_to_framebuffer(connector, false, rounded_buffer_size, rounded_buffer_size));
+ return {};
+}
+
+void VirtIOGraphicsAdapter::set_dirty_displayed_rect(Badge<VirtIODisplayConnector>, VirtIODisplayConnector& connector, Graphics::VirtIOGPU::Protocol::Rect const& dirty_rect, bool main_buffer)
+{
+ VERIFY(m_operation_lock.is_locked());
+ VERIFY(connector.scanout_id() < VIRTIO_GPU_MAX_SCANOUTS);
+ Scanout::PhysicalBuffer& buffer = main_buffer ? m_scanouts[connector.scanout_id().value()].main_buffer : m_scanouts[connector.scanout_id().value()].back_buffer;
+ if (buffer.dirty_rect.width == 0 || buffer.dirty_rect.height == 0) {
+ buffer.dirty_rect = dirty_rect;
+ } else {
+ auto current_dirty_right = buffer.dirty_rect.x + buffer.dirty_rect.width;
+ auto current_dirty_bottom = buffer.dirty_rect.y + buffer.dirty_rect.height;
+ buffer.dirty_rect.x = min(buffer.dirty_rect.x, dirty_rect.x);
+ buffer.dirty_rect.y = min(buffer.dirty_rect.y, dirty_rect.y);
+ buffer.dirty_rect.width = max(current_dirty_right, dirty_rect.x + dirty_rect.width) - buffer.dirty_rect.x;
+ buffer.dirty_rect.height = max(current_dirty_bottom, dirty_rect.y + dirty_rect.height) - buffer.dirty_rect.y;
+ }
+}
+
+void VirtIOGraphicsAdapter::flush_displayed_image(Badge<VirtIODisplayConnector>, VirtIODisplayConnector& connector, Graphics::VirtIOGPU::Protocol::Rect const& dirty_rect, bool main_buffer)
+{
+ VERIFY(m_operation_lock.is_locked());
+ VERIFY(connector.scanout_id() < VIRTIO_GPU_MAX_SCANOUTS);
+ Scanout::PhysicalBuffer& buffer = main_buffer ? m_scanouts[connector.scanout_id().value()].main_buffer : m_scanouts[connector.scanout_id().value()].back_buffer;
+ flush_displayed_image(buffer.resource_id, dirty_rect);
+ buffer.dirty_rect = {};
+}
+
+void VirtIOGraphicsAdapter::transfer_framebuffer_data_to_host(Badge<VirtIODisplayConnector>, VirtIODisplayConnector& connector, Graphics::VirtIOGPU::Protocol::Rect const& rect, bool main_buffer)
+{
+ VERIFY(m_operation_lock.is_locked());
+ VERIFY(connector.scanout_id() < VIRTIO_GPU_MAX_SCANOUTS);
+ Scanout::PhysicalBuffer& buffer = main_buffer ? m_scanouts[connector.scanout_id().value()].main_buffer : m_scanouts[connector.scanout_id().value()].back_buffer;
+ transfer_framebuffer_data_to_host(connector.scanout_id(), buffer.resource_id, rect);
+}
+
+ErrorOr<void> VirtIOGraphicsAdapter::attach_physical_range_to_framebuffer(VirtIODisplayConnector& connector, bool main_buffer, size_t framebuffer_offset, size_t framebuffer_size)
+{
+ VERIFY(m_operation_lock.is_locked());
+ Scanout::PhysicalBuffer& buffer = main_buffer ? m_scanouts[connector.scanout_id().value()].main_buffer : m_scanouts[connector.scanout_id().value()].back_buffer;
+ buffer.framebuffer_offset = framebuffer_offset;
+
+ // 1. Create BUFFER using VIRTIO_GPU_CMD_RESOURCE_CREATE_2D
+ if (buffer.resource_id.value() != 0)
+ delete_resource(buffer.resource_id);
+ auto display_info = connector.display_information({});
+ buffer.resource_id = create_2d_resource(display_info.rect);
+
+ // 2. Attach backing storage using VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING
+ ensure_backing_storage(buffer.resource_id, connector.framebuffer_region(), buffer.framebuffer_offset, framebuffer_size);
+ // 3. Use VIRTIO_GPU_CMD_SET_SCANOUT to link the framebuffer to a display scanout.
+ set_scanout_resource(connector.scanout_id(), buffer.resource_id, display_info.rect);
+ // 4. Render our test pattern
+ connector.draw_ntsc_test_pattern({});
+ // 5. Use VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D to update the host resource from guest memory.
+ transfer_framebuffer_data_to_host(connector.scanout_id(), buffer.resource_id, display_info.rect);
+ // 6. Use VIRTIO_GPU_CMD_RESOURCE_FLUSH to flush the updated resource to the display.
+ flush_displayed_image(buffer.resource_id, display_info.rect);
+
+ // Make sure we constrain the existing dirty rect (if any)
+ if (buffer.dirty_rect.width != 0 || buffer.dirty_rect.height != 0) {
+ auto dirty_right = buffer.dirty_rect.x + buffer.dirty_rect.width;
+ auto dirty_bottom = buffer.dirty_rect.y + buffer.dirty_rect.height;
+ buffer.dirty_rect.width = min(dirty_right, display_info.rect.x + display_info.rect.width) - buffer.dirty_rect.x;
+ buffer.dirty_rect.height = min(dirty_bottom, display_info.rect.y + display_info.rect.height) - buffer.dirty_rect.y;
+ }
+ return {};
+}
+
VirtIOGraphicsAdapter::VirtIOGraphicsAdapter(PCI::DeviceIdentifier const& device_identifier, NonnullOwnPtr<Memory::Region> scratch_space_region)
: VirtIO::Device(device_identifier)
, m_scratch_space(move(scratch_space_region))
diff --git a/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h b/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h
index 2e90d84f63..e4eab527d7 100644
--- a/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h
+++ b/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h
@@ -50,10 +50,25 @@ public:
Graphics::VirtIOGPU::ResourceID allocate_resource_id(Badge<VirtIODisplayConnector>);
Graphics::VirtIOGPU::ContextID allocate_context_id(Badge<VirtIODisplayConnector>);
+ ErrorOr<void> mode_set_resolution(Badge<VirtIODisplayConnector>, VirtIODisplayConnector&, size_t width, size_t height);
+ void set_dirty_displayed_rect(Badge<VirtIODisplayConnector>, VirtIODisplayConnector&, Graphics::VirtIOGPU::Protocol::Rect const& dirty_rect, bool main_buffer);
+ void flush_displayed_image(Badge<VirtIODisplayConnector>, VirtIODisplayConnector&, Graphics::VirtIOGPU::Protocol::Rect const& dirty_rect, bool main_buffer);
+ void transfer_framebuffer_data_to_host(Badge<VirtIODisplayConnector>, VirtIODisplayConnector&, Graphics::VirtIOGPU::Protocol::Rect const& rect, bool main_buffer);
+
private:
+ ErrorOr<void> attach_physical_range_to_framebuffer(VirtIODisplayConnector& connector, bool main_buffer, size_t framebuffer_offset, size_t framebuffer_size);
+
void flush_dirty_rectangle(Graphics::VirtIOGPU::ScanoutID, Graphics::VirtIOGPU::ResourceID, Graphics::VirtIOGPU::Protocol::Rect const& dirty_rect);
struct Scanout {
+ struct PhysicalBuffer {
+ size_t framebuffer_offset { 0 };
+ Graphics::VirtIOGPU::Protocol::Rect dirty_rect {};
+ Graphics::VirtIOGPU::ResourceID resource_id { 0 };
+ };
+
RefPtr<VirtIODisplayConnector> display_connector;
+ PhysicalBuffer main_buffer;
+ PhysicalBuffer back_buffer;
};
VirtIOGraphicsAdapter(PCI::DeviceIdentifier const&, NonnullOwnPtr<Memory::Region> scratch_space_region);
@@ -65,6 +80,13 @@ private:
u32 get_pending_events();
void clear_pending_events(u32 event_bitmask);
+ // 2D framebuffer stuff
+ static ErrorOr<FlatPtr> calculate_framebuffer_size(size_t width, size_t height)
+ {
+ // VirtIO resources can only map on page boundaries!
+ return Memory::page_round_up(sizeof(u32) * width * height);
+ }
+
// 3D Command stuff
Graphics::VirtIOGPU::ContextID create_context();
void attach_resource_to_context(Graphics::VirtIOGPU::ResourceID resource_id, Graphics::VirtIOGPU::ContextID context_id);