mirror of
https://github.com/RGBCube/serenity
synced 2025-07-23 17:37:34 +00:00
WindowServer: Fallback to safe mode-setting in case of mapping overflow
In case of possible framebuffer mapping overflow, just fallback to the safe mode-setting of the DisplayConnector, because in that state we know for sure that we can map a usable framebuffer (otherwise it is a bug in the Kernel, and not WindowServer).
This commit is contained in:
parent
d5b97eb41e
commit
13e9947b4b
6 changed files with 37 additions and 2 deletions
|
@ -51,8 +51,27 @@ HardwareScreenBackend::~HardwareScreenBackend()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorOr<void> HardwareScreenBackend::set_safe_head_mode_setting()
|
||||||
|
{
|
||||||
|
auto rc = graphics_connector_set_safe_head_mode_setting(m_display_connector_fd);
|
||||||
|
if (rc != 0) {
|
||||||
|
dbgln("Failed to set backend safe mode setting: aborting");
|
||||||
|
return Error::from_syscall("graphics_connector_set_safe_head_mode_setting"sv, rc);
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
ErrorOr<void> HardwareScreenBackend::set_head_mode_setting(GraphicsHeadModeSetting mode_setting)
|
ErrorOr<void> HardwareScreenBackend::set_head_mode_setting(GraphicsHeadModeSetting mode_setting)
|
||||||
{
|
{
|
||||||
|
size_t size_in_bytes = 0;
|
||||||
|
if (m_can_set_head_buffer) {
|
||||||
|
size_in_bytes = mode_setting.horizontal_stride * mode_setting.vertical_active * 2;
|
||||||
|
} else {
|
||||||
|
size_in_bytes = mode_setting.horizontal_stride * mode_setting.vertical_active;
|
||||||
|
}
|
||||||
|
VERIFY(size_in_bytes != 0);
|
||||||
|
if (m_max_size_in_bytes < size_in_bytes)
|
||||||
|
return Error::from_errno(EOVERFLOW);
|
||||||
|
|
||||||
GraphicsHeadModeSetting requested_mode_setting = mode_setting;
|
GraphicsHeadModeSetting requested_mode_setting = mode_setting;
|
||||||
auto rc = graphics_connector_set_head_mode_setting(m_display_connector_fd, &requested_mode_setting);
|
auto rc = graphics_connector_set_head_mode_setting(m_display_connector_fd, &requested_mode_setting);
|
||||||
|
@ -91,6 +110,9 @@ ErrorOr<void> HardwareScreenBackend::map_framebuffer()
|
||||||
} else {
|
} else {
|
||||||
m_size_in_bytes = mode_setting.horizontal_stride * mode_setting.vertical_active;
|
m_size_in_bytes = mode_setting.horizontal_stride * mode_setting.vertical_active;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_max_size_in_bytes < m_size_in_bytes)
|
||||||
|
return Error::from_errno(EOVERFLOW);
|
||||||
m_framebuffer = (Gfx::ARGB32*)TRY(Core::System::mmap(nullptr, m_size_in_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, m_display_connector_fd, 0));
|
m_framebuffer = (Gfx::ARGB32*)TRY(Core::System::mmap(nullptr, m_size_in_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, m_display_connector_fd, 0));
|
||||||
|
|
||||||
if (m_can_set_head_buffer) {
|
if (m_can_set_head_buffer) {
|
||||||
|
|
|
@ -31,6 +31,8 @@ public:
|
||||||
virtual ErrorOr<void> unmap_framebuffer() override;
|
virtual ErrorOr<void> unmap_framebuffer() override;
|
||||||
virtual ErrorOr<void> map_framebuffer() override;
|
virtual ErrorOr<void> map_framebuffer() override;
|
||||||
|
|
||||||
|
virtual ErrorOr<void> set_safe_head_mode_setting() override;
|
||||||
|
|
||||||
virtual ErrorOr<void> set_head_mode_setting(GraphicsHeadModeSetting) override;
|
virtual ErrorOr<void> set_head_mode_setting(GraphicsHeadModeSetting) override;
|
||||||
virtual ErrorOr<GraphicsHeadModeSetting> get_head_mode_setting() override;
|
virtual ErrorOr<GraphicsHeadModeSetting> get_head_mode_setting() override;
|
||||||
|
|
||||||
|
|
|
@ -370,12 +370,15 @@ bool Screen::set_resolution(bool initial)
|
||||||
if (!return_value.is_error())
|
if (!return_value.is_error())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (return_value.is_error()) {
|
if (return_value.is_error() && return_value.error() != Error::from_errno(EOVERFLOW)) {
|
||||||
dbgln("Screen #{}: Failed to set resolution {}: {}", index(), info.resolution, return_value.error());
|
dbgln("Screen #{}: Failed to set resolution {}: {}", index(), info.resolution, return_value.error());
|
||||||
MUST(on_change_resolution());
|
MUST(on_change_resolution());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
VERIFY_NOT_REACHED();
|
dbgln("Screen #{}: Failed to set resolution {}: {}, falling back to safe resolution", index(), info.resolution, return_value.error());
|
||||||
|
MUST(m_backend->set_safe_head_mode_setting());
|
||||||
|
MUST(on_change_resolution());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::set_buffer(int index)
|
void Screen::set_buffer(int index)
|
||||||
|
|
|
@ -35,6 +35,7 @@ public:
|
||||||
virtual ErrorOr<void> flush_framebuffer() = 0;
|
virtual ErrorOr<void> flush_framebuffer() = 0;
|
||||||
|
|
||||||
virtual ErrorOr<void> set_head_mode_setting(GraphicsHeadModeSetting) = 0;
|
virtual ErrorOr<void> set_head_mode_setting(GraphicsHeadModeSetting) = 0;
|
||||||
|
virtual ErrorOr<void> set_safe_head_mode_setting() = 0;
|
||||||
virtual ErrorOr<GraphicsHeadModeSetting> get_head_mode_setting() = 0;
|
virtual ErrorOr<GraphicsHeadModeSetting> get_head_mode_setting() = 0;
|
||||||
|
|
||||||
bool m_can_device_flush_buffers { true };
|
bool m_can_device_flush_buffers { true };
|
||||||
|
|
|
@ -31,6 +31,11 @@ void VirtualScreenBackend::set_head_buffer(int index)
|
||||||
m_first_buffer_active = index == 0;
|
m_first_buffer_active = index == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorOr<void> VirtualScreenBackend::set_safe_head_mode_setting()
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
ErrorOr<void> VirtualScreenBackend::set_head_mode_setting(GraphicsHeadModeSetting mode_setting)
|
ErrorOr<void> VirtualScreenBackend::set_head_mode_setting(GraphicsHeadModeSetting mode_setting)
|
||||||
{
|
{
|
||||||
m_height = mode_setting.vertical_active;
|
m_height = mode_setting.vertical_active;
|
||||||
|
|
|
@ -35,6 +35,8 @@ private:
|
||||||
virtual ErrorOr<void> unmap_framebuffer() override;
|
virtual ErrorOr<void> unmap_framebuffer() override;
|
||||||
virtual ErrorOr<void> map_framebuffer() override;
|
virtual ErrorOr<void> map_framebuffer() override;
|
||||||
|
|
||||||
|
virtual ErrorOr<void> set_safe_head_mode_setting() override;
|
||||||
|
|
||||||
virtual ErrorOr<void> set_head_mode_setting(GraphicsHeadModeSetting) override;
|
virtual ErrorOr<void> set_head_mode_setting(GraphicsHeadModeSetting) override;
|
||||||
virtual ErrorOr<GraphicsHeadModeSetting> get_head_mode_setting() override;
|
virtual ErrorOr<GraphicsHeadModeSetting> get_head_mode_setting() override;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue