Serenity Operating System
at master 133 lines 5.7 kB view raw
1/* 2 * Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <Kernel/Devices/DeviceManagement.h> 8#include <Kernel/Graphics/GraphicsManagement.h> 9#include <Kernel/Graphics/VMWare/Console.h> 10#include <Kernel/Graphics/VMWare/DisplayConnector.h> 11 12namespace Kernel { 13 14NonnullLockRefPtr<VMWareDisplayConnector> VMWareDisplayConnector::must_create(VMWareGraphicsAdapter const& parent_adapter, PhysicalAddress framebuffer_address, size_t framebuffer_resource_size) 15{ 16 auto connector = MUST(DeviceManagement::try_create_device<VMWareDisplayConnector>(parent_adapter, framebuffer_address, framebuffer_resource_size)); 17 MUST(connector->create_attached_framebuffer_console()); 18 MUST(connector->initialize_edid_for_generic_monitor(Array<u8, 3> { 'V', 'M', 'W' })); 19 return connector; 20} 21 22ErrorOr<void> VMWareDisplayConnector::create_attached_framebuffer_console() 23{ 24 m_framebuffer_console = VMWareFramebufferConsole::initialize(*this); 25 GraphicsManagement::the().set_console(*m_framebuffer_console); 26 return {}; 27} 28 29VMWareDisplayConnector::VMWareDisplayConnector(VMWareGraphicsAdapter const& parent_adapter, PhysicalAddress framebuffer_address, size_t framebuffer_resource_size) 30 : DisplayConnector(framebuffer_address, framebuffer_resource_size, false) 31 , m_parent_adapter(parent_adapter) 32{ 33} 34 35ErrorOr<void> VMWareDisplayConnector::set_safe_mode_setting() 36{ 37 // We assume safe resolution is 1024x768x32 38 DisplayConnector::ModeSetting safe_mode_setting { 39 .horizontal_stride = 1024 * sizeof(u32), 40 .pixel_clock_in_khz = 0, // Note: There's no pixel clock in paravirtualized hardware 41 .horizontal_active = 1024, 42 .horizontal_front_porch_pixels = 0, // Note: There's no horizontal_front_porch_pixels in paravirtualized hardware 43 .horizontal_sync_time_pixels = 0, // Note: There's no horizontal_sync_time_pixels in paravirtualized hardware 44 .horizontal_blank_pixels = 0, // Note: There's no horizontal_blank_pixels in paravirtualized hardware 45 .vertical_active = 768, 46 .vertical_front_porch_lines = 0, // Note: There's no vertical_front_porch_lines in paravirtualized hardware 47 .vertical_sync_time_lines = 0, // Note: There's no vertical_sync_time_lines in paravirtualized hardware 48 .vertical_blank_lines = 0, // Note: There's no vertical_blank_lines in paravirtualized hardware 49 .horizontal_offset = 0, 50 .vertical_offset = 0, 51 }; 52 return set_mode_setting(safe_mode_setting); 53} 54 55ErrorOr<void> VMWareDisplayConnector::unblank() 56{ 57 return Error::from_errno(ENOTIMPL); 58} 59 60void VMWareDisplayConnector::enable_console() 61{ 62 VERIFY(m_control_lock.is_locked()); 63 VERIFY(m_framebuffer_console); 64 m_framebuffer_console->enable(); 65} 66 67void VMWareDisplayConnector::disable_console() 68{ 69 VERIFY(m_control_lock.is_locked()); 70 VERIFY(m_framebuffer_console); 71 m_framebuffer_console->disable(); 72} 73 74ErrorOr<void> VMWareDisplayConnector::flush_first_surface() 75{ 76 // FIXME: Cache these values but keep them in sync with the parent adapter. 77 auto width = m_parent_adapter->primary_screen_width({}); 78 auto height = m_parent_adapter->primary_screen_height({}); 79 m_parent_adapter->primary_screen_flush({}, width, height); 80 return {}; 81} 82 83ErrorOr<void> VMWareDisplayConnector::set_y_offset(size_t) 84{ 85 return Error::from_errno(ENOTSUP); 86} 87 88ErrorOr<void> VMWareDisplayConnector::flush_rectangle(size_t, FBRect const&) 89{ 90 // FIXME: It costs really nothing to flush the entire screen (at least in QEMU). 91 // Try to implement better partial rectangle flush method instead here. 92 VERIFY(m_flushing_lock.is_locked()); 93 // FIXME: Cache these values but keep them in sync with the parent adapter. 94 auto width = m_parent_adapter->primary_screen_width({}); 95 auto height = m_parent_adapter->primary_screen_height({}); 96 m_parent_adapter->primary_screen_flush({}, width, height); 97 return {}; 98} 99 100ErrorOr<void> VMWareDisplayConnector::set_mode_setting(ModeSetting const& mode_setting) 101{ 102 SpinlockLocker locker(m_modeset_lock); 103 VERIFY(m_framebuffer_console); 104 size_t width = mode_setting.horizontal_active; 105 size_t height = mode_setting.vertical_active; 106 107 if (Checked<size_t>::multiplication_would_overflow(width, height, sizeof(u32))) 108 return EOVERFLOW; 109 110 TRY(m_parent_adapter->modeset_primary_screen_resolution({}, width, height)); 111 112 m_framebuffer_console->set_resolution(width, height, width * sizeof(u32)); 113 114 auto pitch = m_parent_adapter->primary_screen_pitch({}); 115 DisplayConnector::ModeSetting current_mode_setting { 116 .horizontal_stride = pitch, 117 .pixel_clock_in_khz = 0, // Note: There's no pixel clock in paravirtualized hardware 118 .horizontal_active = width, 119 .horizontal_front_porch_pixels = 0, // Note: There's no horizontal_front_porch_pixels in paravirtualized hardware 120 .horizontal_sync_time_pixels = 0, // Note: There's no horizontal_sync_time_pixels in paravirtualized hardware 121 .horizontal_blank_pixels = 0, // Note: There's no horizontal_blank_pixels in paravirtualized hardware 122 .vertical_active = height, 123 .vertical_front_porch_lines = 0, // Note: There's no vertical_front_porch_lines in paravirtualized hardware 124 .vertical_sync_time_lines = 0, // Note: There's no vertical_sync_time_lines in paravirtualized hardware 125 .vertical_blank_lines = 0, // Note: There's no vertical_blank_lines in paravirtualized hardware 126 .horizontal_offset = 0, 127 .vertical_offset = 0, 128 }; 129 m_current_mode_setting = current_mode_setting; 130 return {}; 131} 132 133}