浏览代码

Kernel/Graphics: Force BGR format when modesetting the bochs-display

By default bochs-display uses the BGR format, but for future-proof
solution, let's force it explicitly to use that format.
Liav A 3 年之前
父节点
当前提交
de1b649783
共有 2 个文件被更改,包括 35 次插入0 次删除
  1. 32 0
      Kernel/Graphics/Bochs/GraphicsAdapter.cpp
  2. 3 0
      Kernel/Graphics/Bochs/GraphicsAdapter.h

+ 32 - 0
Kernel/Graphics/Bochs/GraphicsAdapter.cpp

@@ -32,6 +32,8 @@
 #define VBE_DISPI_DISABLED 0x00
 #define VBE_DISPI_ENABLED 0x01
 #define VBE_DISPI_LFB_ENABLED 0x40
+#define BOCHS_DISPLAY_LITTLE_ENDIAN 0x1e1e1e1e
+#define BOCHS_DISPLAY_BIG_ENDIAN 0xbebebebe
 
 namespace Kernel {
 
@@ -48,11 +50,18 @@ struct [[gnu::packed]] DISPIInterface {
     u16 y_offset;
 };
 
+struct [[gnu::packed]] ExtensionRegisters {
+    u32 region_size;
+    u32 framebuffer_byteorder;
+};
+
 struct [[gnu::packed]] BochsDisplayMMIORegisters {
     u8 edid_data[0x400];
     u16 vga_ioports[0x10];
     u8 reserved[0xE0];
     DISPIInterface bochs_regs;
+    u8 reserved2[0x100 - sizeof(DISPIInterface)];
+    ExtensionRegisters extension_regs;
 };
 
 UNMAP_AFTER_INIT NonnullRefPtr<BochsGraphicsAdapter> BochsGraphicsAdapter::initialize(PCI::Address address)
@@ -62,6 +71,28 @@ UNMAP_AFTER_INIT NonnullRefPtr<BochsGraphicsAdapter> BochsGraphicsAdapter::initi
     return adopt_ref(*new BochsGraphicsAdapter(address));
 }
 
+void BochsGraphicsAdapter::set_framebuffer_to_big_endian_format()
+{
+    dbgln_if(BXVGA_DEBUG, "BochsGraphicsAdapter set_framebuffer_to_big_endian_format");
+    full_memory_barrier();
+    if (m_registers->extension_regs.region_size == 0xFFFFFFFF || m_registers->extension_regs.region_size == 0)
+        return;
+    full_memory_barrier();
+    m_registers->extension_regs.framebuffer_byteorder = BOCHS_DISPLAY_BIG_ENDIAN;
+    full_memory_barrier();
+}
+
+void BochsGraphicsAdapter::set_framebuffer_to_little_endian_format()
+{
+    dbgln_if(BXVGA_DEBUG, "BochsGraphicsAdapter set_framebuffer_to_little_endian_format");
+    full_memory_barrier();
+    if (m_registers->extension_regs.region_size == 0xFFFFFFFF || m_registers->extension_regs.region_size == 0)
+        return;
+    full_memory_barrier();
+    m_registers->extension_regs.framebuffer_byteorder = BOCHS_DISPLAY_LITTLE_ENDIAN;
+    full_memory_barrier();
+}
+
 UNMAP_AFTER_INIT BochsGraphicsAdapter::BochsGraphicsAdapter(PCI::Address pci_address)
     : PCI::Device(pci_address)
     , m_mmio_registers(PCI::get_BAR2(pci_address) & 0xfffffff0)
@@ -153,6 +184,7 @@ void BochsGraphicsAdapter::set_resolution_registers(size_t width, size_t height)
     m_registers->bochs_regs.enable = VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED;
     full_memory_barrier();
     m_registers->bochs_regs.bank = 0;
+    set_framebuffer_to_little_endian_format();
 }
 
 bool BochsGraphicsAdapter::try_to_set_resolution(size_t output_port_index, size_t width, size_t height)

+ 3 - 0
Kernel/Graphics/Bochs/GraphicsAdapter.h

@@ -56,6 +56,9 @@ private:
     bool validate_setup_resolution_with_io(size_t width, size_t height);
     void set_y_offset(size_t);
 
+    void set_framebuffer_to_big_endian_format();
+    void set_framebuffer_to_little_endian_format();
+
     PhysicalAddress m_mmio_registers;
     Memory::TypedMapping<BochsDisplayMMIORegisters volatile> m_registers;
     RefPtr<FramebufferDevice> m_framebuffer_device;