Browse Source

Kernel/Graphics: Use DisplayConnector design with generic framebuffers

Liav A 3 years ago
parent
commit
f15b93c9a1

+ 2 - 0
Kernel/CMakeLists.txt

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

+ 1 - 1
Kernel/Graphics/Console/VGAConsole.h

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

+ 1 - 1
Kernel/Graphics/GraphicsManagement.cpp

@@ -15,7 +15,7 @@
 #include <Kernel/Graphics/Intel/NativeGraphicsAdapter.h>
 #include <Kernel/Graphics/VGA/ISAAdapter.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/Memory/AnonymousVMObject.h>
 #include <Kernel/Multiboot.h>

+ 1 - 1
Kernel/Graphics/GraphicsManagement.h

@@ -14,7 +14,7 @@
 #include <Kernel/Graphics/Console/Console.h>
 #include <Kernel/Graphics/DisplayConnector.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/Memory/Region.h>
 

+ 78 - 0
Kernel/Graphics/VGA/DisplayConnector.cpp

@@ -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);
+}
+
+}

+ 53 - 0
Kernel/Graphics/VGA/DisplayConnector.h

@@ -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 {};
+};
+}

+ 0 - 24
Kernel/Graphics/VGA/ISAAdapter.cpp

@@ -23,28 +23,4 @@ UNMAP_AFTER_INIT ISAVGAAdapter::ISAVGAAdapter()
     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;
-}
-
 }

+ 1 - 13
Kernel/Graphics/VGA/ISAAdapter.h

@@ -11,6 +11,7 @@
 #include <Kernel/Graphics/Console/Console.h>
 #include <Kernel/Graphics/FramebufferDevice.h>
 #include <Kernel/Graphics/GenericGraphicsAdapter.h>
+#include <Kernel/Graphics/VGA/VGACompatibleAdapter.h>
 #include <Kernel/PhysicalAddress.h>
 
 namespace Kernel {
@@ -21,21 +22,8 @@ class ISAVGAAdapter final : public VGACompatibleAdapter {
 public:
     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:
     ISAVGAAdapter();
-
-    // ^GenericGraphicsAdapter
-    virtual void initialize_framebuffer_devices() override;
-
-    virtual void enable_consoles() override;
-    virtual void disable_consoles() override;
-
     RefPtr<Graphics::Console> m_framebuffer_console;
 };
 }

+ 6 - 45
Kernel/Graphics/VGA/PCIAdapter.cpp

@@ -12,61 +12,22 @@
 
 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)
 {
-    return adopt_ref(*new PCIVGACompatibleAdapter(pci_device_identifier.address()));
-}
-
-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());
+    auto adapter = adopt_ref(*new PCIVGACompatibleAdapter(pci_device_identifier.address()));
+    return adapter;
 }
 
 UNMAP_AFTER_INIT PCIVGACompatibleAdapter::PCIVGACompatibleAdapter(PCI::Address 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();
 }
 
 }

+ 0 - 19
Kernel/Graphics/VGA/PCIAdapter.h

@@ -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(PCI::DeviceIdentifier const&);
 
-    virtual bool framebuffer_devices_initialized() const override { return !m_framebuffer_device.is_null(); }
-
 protected:
     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;
 };
 }

+ 20 - 0
Kernel/Graphics/VGA/VGACompatibleAdapter.cpp

@@ -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);
+}
+
+}

+ 40 - 0
Kernel/Graphics/VGA/VGACompatibleAdapter.h

@@ -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;
+};
+}

+ 0 - 35
Kernel/Graphics/VGACompatibleAdapter.h

@@ -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;
-};
-}