1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-25 07:35:07 +00:00

Kernel/Graphics: Use DisplayConnector design with generic framebuffers

This commit is contained in:
Liav A 2022-04-30 14:35:22 +03:00 committed by Andreas Kling
parent c27c414ed1
commit f15b93c9a1
13 changed files with 203 additions and 139 deletions

View file

@ -87,8 +87,10 @@ set(KERNEL_SOURCES
Graphics/GraphicsManagement.cpp Graphics/GraphicsManagement.cpp
Graphics/Intel/NativeDisplayConnector.cpp Graphics/Intel/NativeDisplayConnector.cpp
Graphics/Intel/NativeGraphicsAdapter.cpp Graphics/Intel/NativeGraphicsAdapter.cpp
Graphics/VGA/DisplayConnector.cpp
Graphics/VGA/ISAAdapter.cpp Graphics/VGA/ISAAdapter.cpp
Graphics/VGA/PCIAdapter.cpp Graphics/VGA/PCIAdapter.cpp
Graphics/VGA/VGACompatibleAdapter.cpp
Graphics/VirtIOGPU/DisplayConnector.cpp Graphics/VirtIOGPU/DisplayConnector.cpp
Graphics/VirtIOGPU/Console.cpp Graphics/VirtIOGPU/Console.cpp
Graphics/VirtIOGPU/GPU3DDevice.cpp Graphics/VirtIOGPU/GPU3DDevice.cpp

View file

@ -9,7 +9,7 @@
#include <AK/RefCounted.h> #include <AK/RefCounted.h>
#include <AK/Types.h> #include <AK/Types.h>
#include <Kernel/Graphics/Console/Console.h> #include <Kernel/Graphics/Console/Console.h>
#include <Kernel/Graphics/VGACompatibleAdapter.h> #include <Kernel/Graphics/VGA/VGACompatibleAdapter.h>
namespace Kernel::Graphics { namespace Kernel::Graphics {
class VGAConsole : public Console { class VGAConsole : public Console {

View file

@ -15,7 +15,7 @@
#include <Kernel/Graphics/Intel/NativeGraphicsAdapter.h> #include <Kernel/Graphics/Intel/NativeGraphicsAdapter.h>
#include <Kernel/Graphics/VGA/ISAAdapter.h> #include <Kernel/Graphics/VGA/ISAAdapter.h>
#include <Kernel/Graphics/VGA/PCIAdapter.h> #include <Kernel/Graphics/VGA/PCIAdapter.h>
#include <Kernel/Graphics/VGACompatibleAdapter.h> #include <Kernel/Graphics/VGA/VGACompatibleAdapter.h>
#include <Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h> #include <Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h>
#include <Kernel/Memory/AnonymousVMObject.h> #include <Kernel/Memory/AnonymousVMObject.h>
#include <Kernel/Multiboot.h> #include <Kernel/Multiboot.h>

View file

@ -14,7 +14,7 @@
#include <Kernel/Graphics/Console/Console.h> #include <Kernel/Graphics/Console/Console.h>
#include <Kernel/Graphics/DisplayConnector.h> #include <Kernel/Graphics/DisplayConnector.h>
#include <Kernel/Graphics/GenericGraphicsAdapter.h> #include <Kernel/Graphics/GenericGraphicsAdapter.h>
#include <Kernel/Graphics/VGACompatibleAdapter.h> #include <Kernel/Graphics/VGA/VGACompatibleAdapter.h>
#include <Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h> #include <Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h>
#include <Kernel/Memory/Region.h> #include <Kernel/Memory/Region.h>

View file

@ -0,0 +1,78 @@
/*
* Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <Kernel/Arch/x86/IO.h>
#include <Kernel/Debug.h>
#include <Kernel/Devices/DeviceManagement.h>
#include <Kernel/Graphics/Console/ContiguousFramebufferConsole.h>
#include <Kernel/Graphics/GraphicsManagement.h>
#include <Kernel/Graphics/VGA/DisplayConnector.h>
namespace Kernel {
NonnullRefPtr<GenericDisplayConnector> GenericDisplayConnector::must_create_with_preset_resolution(PhysicalAddress framebuffer_address, size_t width, size_t height, size_t pitch)
{
auto device_or_error = DeviceManagement::try_create_device<GenericDisplayConnector>(framebuffer_address, width, height, pitch);
VERIFY(!device_or_error.is_error());
auto connector = device_or_error.release_value();
MUST(connector->create_attached_framebuffer_console());
MUST(connector->initialize_edid_for_generic_monitor());
return connector;
}
GenericDisplayConnector::GenericDisplayConnector(PhysicalAddress framebuffer_address, size_t width, size_t height, size_t pitch)
: DisplayConnector()
, m_framebuffer_address(framebuffer_address)
{
m_current_mode_setting.horizontal_active = width;
m_current_mode_setting.vertical_active = height;
m_current_mode_setting.horizontal_stride = pitch;
}
ErrorOr<void> GenericDisplayConnector::create_attached_framebuffer_console()
{
auto width = m_current_mode_setting.horizontal_active;
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);
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());
VERIFY(m_framebuffer_console);
m_framebuffer_console->enable();
}
void GenericDisplayConnector::disable_console()
{
VERIFY(m_control_lock.is_locked());
VERIFY(m_framebuffer_console);
m_framebuffer_console->disable();
}
ErrorOr<void> GenericDisplayConnector::flush_first_surface()
{
return Error::from_errno(ENOTSUP);
}
}

View file

@ -0,0 +1,53 @@
/*
* Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/RefPtr.h>
#include <AK/Try.h>
#include <Kernel/Graphics/Console/GenericFramebufferConsole.h>
#include <Kernel/Graphics/DisplayConnector.h>
#include <Kernel/Locking/Spinlock.h>
#include <Kernel/Memory/TypedMapping.h>
namespace Kernel {
class GenericDisplayConnector
: public DisplayConnector {
friend class DeviceManagement;
public:
static NonnullRefPtr<GenericDisplayConnector> must_create_with_preset_resolution(PhysicalAddress framebuffer_address, size_t width, size_t height, size_t pitch);
protected:
ErrorOr<void> create_attached_framebuffer_console();
GenericDisplayConnector(PhysicalAddress framebuffer_address, size_t width, size_t height, size_t pitch);
virtual bool mutable_mode_setting_capable() const override final { return false; }
virtual bool double_framebuffering_capable() const override { return false; }
virtual ErrorOr<void> set_mode_setting(ModeSetting const&) override { return Error::from_errno(ENOTSUP); }
virtual ErrorOr<void> set_safe_mode_setting() override { return {}; }
virtual ErrorOr<void> set_y_offset(size_t) override { return Error::from_errno(ENOTSUP); }
virtual ErrorOr<void> unblank() override { return Error::from_errno(ENOTSUP); }
virtual bool partial_flush_support() const override final { return false; }
virtual bool flush_support() const override final { return false; }
// 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 {};
};
}

View file

@ -23,28 +23,4 @@ UNMAP_AFTER_INIT ISAVGAAdapter::ISAVGAAdapter()
GraphicsManagement::the().set_console(*m_framebuffer_console); GraphicsManagement::the().set_console(*m_framebuffer_console);
} }
void ISAVGAAdapter::enable_consoles()
{
VERIFY(m_framebuffer_console);
m_framebuffer_console->enable();
}
void ISAVGAAdapter::disable_consoles()
{
VERIFY(m_framebuffer_console);
m_framebuffer_console->disable();
}
void ISAVGAAdapter::initialize_framebuffer_devices()
{
}
bool ISAVGAAdapter::try_to_set_resolution(size_t, size_t, size_t)
{
return false;
}
bool ISAVGAAdapter::set_y_offset(size_t, size_t)
{
return false;
}
} }

View file

@ -11,6 +11,7 @@
#include <Kernel/Graphics/Console/Console.h> #include <Kernel/Graphics/Console/Console.h>
#include <Kernel/Graphics/FramebufferDevice.h> #include <Kernel/Graphics/FramebufferDevice.h>
#include <Kernel/Graphics/GenericGraphicsAdapter.h> #include <Kernel/Graphics/GenericGraphicsAdapter.h>
#include <Kernel/Graphics/VGA/VGACompatibleAdapter.h>
#include <Kernel/PhysicalAddress.h> #include <Kernel/PhysicalAddress.h>
namespace Kernel { namespace Kernel {
@ -21,21 +22,8 @@ class ISAVGAAdapter final : public VGACompatibleAdapter {
public: public:
static NonnullRefPtr<ISAVGAAdapter> initialize(); static NonnullRefPtr<ISAVGAAdapter> initialize();
// Note: We simply don't support old VGA framebuffer modes (like the 320x200 256-colors one)
virtual bool framebuffer_devices_initialized() const override { return false; }
virtual bool try_to_set_resolution(size_t output_port_index, size_t width, size_t height) override;
virtual bool set_y_offset(size_t output_port_index, size_t y) override;
private: private:
ISAVGAAdapter(); ISAVGAAdapter();
// ^GenericGraphicsAdapter
virtual void initialize_framebuffer_devices() override;
virtual void enable_consoles() override;
virtual void disable_consoles() override;
RefPtr<Graphics::Console> m_framebuffer_console; RefPtr<Graphics::Console> m_framebuffer_console;
}; };
} }

View file

@ -12,61 +12,22 @@
namespace Kernel { namespace Kernel {
UNMAP_AFTER_INIT NonnullRefPtr<PCIVGACompatibleAdapter> PCIVGACompatibleAdapter::initialize_with_preset_resolution(PCI::DeviceIdentifier const& pci_device_identifier, PhysicalAddress m_framebuffer_address, size_t framebuffer_width, size_t framebuffer_height, size_t framebuffer_pitch) UNMAP_AFTER_INIT NonnullRefPtr<PCIVGACompatibleAdapter> PCIVGACompatibleAdapter::initialize_with_preset_resolution(PCI::DeviceIdentifier const& pci_device_identifier, PhysicalAddress framebuffer_address, size_t framebuffer_width, size_t framebuffer_height, size_t framebuffer_pitch)
{ {
return adopt_ref(*new PCIVGACompatibleAdapter(pci_device_identifier.address(), m_framebuffer_address, framebuffer_width, framebuffer_height, framebuffer_pitch)); auto adapter = adopt_ref(*new PCIVGACompatibleAdapter(pci_device_identifier.address()));
adapter->initialize_display_connector_with_preset_resolution(framebuffer_address, framebuffer_width, framebuffer_height, framebuffer_pitch);
return adapter;
} }
UNMAP_AFTER_INIT NonnullRefPtr<PCIVGACompatibleAdapter> PCIVGACompatibleAdapter::initialize(PCI::DeviceIdentifier const& pci_device_identifier) UNMAP_AFTER_INIT NonnullRefPtr<PCIVGACompatibleAdapter> PCIVGACompatibleAdapter::initialize(PCI::DeviceIdentifier const& pci_device_identifier)
{ {
return adopt_ref(*new PCIVGACompatibleAdapter(pci_device_identifier.address())); auto adapter = adopt_ref(*new PCIVGACompatibleAdapter(pci_device_identifier.address()));
} return adapter;
UNMAP_AFTER_INIT void PCIVGACompatibleAdapter::initialize_framebuffer_devices()
{
// We might not have any pre-set framebuffer, so if that's the case - don't try to initialize one.
if (m_framebuffer_address.is_null())
return;
VERIFY(m_framebuffer_width);
VERIFY(m_framebuffer_width != 0);
VERIFY(m_framebuffer_height != 0);
VERIFY(m_framebuffer_pitch != 0);
m_framebuffer_device = FramebufferDevice::create(*this, m_framebuffer_address, m_framebuffer_width, m_framebuffer_height, m_framebuffer_pitch);
// FIXME: Would be nice to be able to return ErrorOr<void> here.
VERIFY(!m_framebuffer_device->try_to_initialize().is_error());
} }
UNMAP_AFTER_INIT PCIVGACompatibleAdapter::PCIVGACompatibleAdapter(PCI::Address address) UNMAP_AFTER_INIT PCIVGACompatibleAdapter::PCIVGACompatibleAdapter(PCI::Address address)
: PCI::Device(address) : PCI::Device(address)
{ {
m_framebuffer_console = Graphics::TextModeConsole::initialize();
GraphicsManagement::the().set_console(*m_framebuffer_console);
}
UNMAP_AFTER_INIT PCIVGACompatibleAdapter::PCIVGACompatibleAdapter(PCI::Address address, PhysicalAddress framebuffer_address, size_t framebuffer_width, size_t framebuffer_height, size_t framebuffer_pitch)
: PCI::Device(address)
, m_framebuffer_address(framebuffer_address)
, m_framebuffer_width(framebuffer_width)
, m_framebuffer_height(framebuffer_height)
, m_framebuffer_pitch(framebuffer_pitch)
{
m_framebuffer_console = Graphics::ContiguousFramebufferConsole::initialize(framebuffer_address, framebuffer_width, framebuffer_height, framebuffer_pitch);
GraphicsManagement::the().set_console(*m_framebuffer_console);
}
void PCIVGACompatibleAdapter::enable_consoles()
{
VERIFY(m_framebuffer_console);
if (m_framebuffer_device)
m_framebuffer_device->deactivate_writes();
m_framebuffer_console->enable();
}
void PCIVGACompatibleAdapter::disable_consoles()
{
VERIFY(m_framebuffer_device);
VERIFY(m_framebuffer_console);
m_framebuffer_console->disable();
m_framebuffer_device->activate_writes();
} }
} }

View file

@ -21,26 +21,7 @@ public:
static NonnullRefPtr<PCIVGACompatibleAdapter> initialize_with_preset_resolution(PCI::DeviceIdentifier const&, PhysicalAddress, size_t framebuffer_width, size_t framebuffer_height, size_t framebuffer_pitch); static NonnullRefPtr<PCIVGACompatibleAdapter> initialize_with_preset_resolution(PCI::DeviceIdentifier const&, PhysicalAddress, size_t framebuffer_width, size_t framebuffer_height, size_t framebuffer_pitch);
static NonnullRefPtr<PCIVGACompatibleAdapter> initialize(PCI::DeviceIdentifier const&); static NonnullRefPtr<PCIVGACompatibleAdapter> initialize(PCI::DeviceIdentifier const&);
virtual bool framebuffer_devices_initialized() const override { return !m_framebuffer_device.is_null(); }
protected: protected:
explicit PCIVGACompatibleAdapter(PCI::Address); explicit PCIVGACompatibleAdapter(PCI::Address);
private:
PCIVGACompatibleAdapter(PCI::Address, PhysicalAddress, size_t framebuffer_width, size_t framebuffer_height, size_t framebuffer_pitch);
// ^GenericGraphicsAdapter
virtual void initialize_framebuffer_devices() override;
virtual void enable_consoles() override;
virtual void disable_consoles() override;
protected:
PhysicalAddress m_framebuffer_address;
size_t m_framebuffer_width { 0 };
size_t m_framebuffer_height { 0 };
size_t m_framebuffer_pitch { 0 };
RefPtr<FramebufferDevice> m_framebuffer_device;
}; };
} }

View file

@ -0,0 +1,20 @@
/*
* Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <Kernel/Graphics/Console/ContiguousFramebufferConsole.h>
#include <Kernel/Graphics/Console/TextModeConsole.h>
#include <Kernel/Graphics/GraphicsManagement.h>
#include <Kernel/Graphics/VGA/VGACompatibleAdapter.h>
#include <Kernel/Sections.h>
namespace Kernel {
void VGACompatibleAdapter::initialize_display_connector_with_preset_resolution(PhysicalAddress framebuffer_address, size_t framebuffer_width, size_t framebuffer_height, size_t framebuffer_pitch)
{
m_generic_display_connector = GenericDisplayConnector::must_create_with_preset_resolution(framebuffer_address, framebuffer_width, framebuffer_height, framebuffer_pitch);
}
}

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2021-2022, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Types.h>
#include <Kernel/Bus/PCI/Device.h>
#include <Kernel/Graphics/Console/Console.h>
#include <Kernel/Graphics/GenericGraphicsAdapter.h>
#include <Kernel/Graphics/VGA/DisplayConnector.h>
#include <Kernel/PhysicalAddress.h>
namespace Kernel {
class VGACompatibleAdapter : public GenericGraphicsAdapter {
public:
virtual bool vga_compatible() const override final { return true; }
protected:
void initialize_display_connector_with_preset_resolution(PhysicalAddress, size_t framebuffer_width, size_t framebuffer_height, size_t framebuffer_pitch);
VGACompatibleAdapter() = default;
// ^GenericGraphicsAdapter
virtual bool modesetting_capable() const override { VERIFY_NOT_REACHED(); }
virtual bool double_framebuffering_capable() const override { VERIFY_NOT_REACHED(); }
virtual bool framebuffer_devices_initialized() const override { return false; }
virtual void initialize_framebuffer_devices() override { }
virtual void enable_consoles() override { }
virtual void disable_consoles() override { }
virtual bool try_to_set_resolution(size_t, size_t, size_t) override { VERIFY_NOT_REACHED(); }
virtual bool set_y_offset(size_t, size_t) override { VERIFY_NOT_REACHED(); }
ErrorOr<ByteBuffer> get_edid(size_t) const override { return Error::from_errno(ENOTSUP); }
RefPtr<GenericDisplayConnector> m_generic_display_connector;
};
}

View file

@ -1,35 +0,0 @@
/*
* Copyright (c) 2021-2022, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Types.h>
#include <Kernel/Bus/PCI/Device.h>
#include <Kernel/Graphics/Console/Console.h>
#include <Kernel/Graphics/FramebufferDevice.h>
#include <Kernel/Graphics/GenericGraphicsAdapter.h>
#include <Kernel/PhysicalAddress.h>
namespace Kernel {
class VGACompatibleAdapter : public GenericGraphicsAdapter {
public:
virtual bool modesetting_capable() const override { return false; }
virtual bool double_framebuffering_capable() const override { return false; }
virtual bool vga_compatible() const override final { return true; }
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; }
ErrorOr<ByteBuffer> get_edid(size_t) const override { return Error::from_errno(ENOTSUP); }
protected:
VGACompatibleAdapter() = default;
RefPtr<Graphics::Console> m_framebuffer_console;
};
}