From a6fb61dbf265fe902587f3c7365ff8694c63a0bf Mon Sep 17 00:00:00 2001 From: Christian Helmuth Date: Tue, 17 Aug 2021 15:26:18 +0200 Subject: [PATCH] vbox6: support dynamic framebuffer resolution Issue #4031 --- repos/ports/src/virtualbox6/include/fb.h | 14 +++++---- repos/ports/src/virtualbox6/main.cc | 38 +++++++++++++++++++++++- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/repos/ports/src/virtualbox6/include/fb.h b/repos/ports/src/virtualbox6/include/fb.h index caec3f8f6f..7847697225 100644 --- a/repos/ports/src/virtualbox6/include/fb.h +++ b/repos/ports/src/virtualbox6/include/fb.h @@ -148,10 +148,13 @@ class Genodefb : /* save the new bitmap reference */ _display->QuerySourceBitmap(screen, _display_bitmap.asOutParam()); - bool ok = (w <= (ULONG)_fb_mode.area.w()) && - (h <= (ULONG)_fb_mode.area.h()); + bool const ok = (w <= (ULONG)_fb_mode.area.w()) && + (h <= (ULONG)_fb_mode.area.h()); - if (ok) { + bool const changed = (w != (ULONG)_virtual_fb_mode.area.w()) || + (h != (ULONG)_virtual_fb_mode.area.h()); + + if (ok && changed) { Genode::log("fb resize : [", screen, "] ", _virtual_fb_mode.area, " -> ", w, "x", h, @@ -160,13 +163,13 @@ class Genodefb : if ((w < (ULONG)_fb_mode.area.w()) || (h < (ULONG)_fb_mode.area.h())) { /* clear the old content around the new, smaller area. */ - _clear_screen(); + _clear_screen(); } _virtual_fb_mode = Fb_Genode::Mode { .area = { w, h } }; result = S_OK; - } else { + } else if (changed) { Genode::log("fb resize : [", screen, "] ", _virtual_fb_mode.area, " -> ", w, "x", h, " ignored" @@ -205,7 +208,6 @@ class Genodefb : Lock(); if (_display_bitmap.isNull()) { - _clear_screen(); Unlock(); return S_OK; } diff --git a/repos/ports/src/virtualbox6/main.cc b/repos/ports/src/virtualbox6/main.cc index e71dde1b82..deac9aff51 100644 --- a/repos/ports/src/virtualbox6/main.cc +++ b/repos/ports/src/virtualbox6/main.cc @@ -265,6 +265,10 @@ struct Main : Event_handler void _handle_input(); + Signal_handler
_fb_mode_handler { _env.ep(), *this, &Main::_handle_fb_mode }; + + void _handle_fb_mode(); + Input_adapter _input_adapter { _iconsole }; bool const _genode_gui_attached = ( _attach_genode_gui(), true ); @@ -275,9 +279,12 @@ struct Main : Event_handler for (unsigned i = 0; i < num_monitors.value; i++) { - Gui::Connection &gui = *new Registered(_gui_connections, _env); + String<3> label { i }; + + Gui::Connection &gui = *new Registered(_gui_connections, _env, label.string()); gui.input()->sigh(_input_handler); + gui.mode_sigh(_fb_mode_handler); Genodefb *fb = new Genodefb(_env, gui, _idisplay); @@ -371,6 +378,35 @@ void Main::_handle_input() } +void Main::_handle_fb_mode() +{ + Libc::with_libc([&] { + _gui_connections.for_each([&] (Gui::Connection &gui) { + IFramebuffer *pFramebuffer = NULL; + HRESULT rc = _idisplay->QueryFramebuffer(0, &pFramebuffer); + Assert(SUCCEEDED(rc) && pFramebuffer); + + Genodefb *fb = dynamic_cast(pFramebuffer); + + fb->update_mode(gui.mode()); + + if ((fb->w() <= 1) && (fb->h() <= 1)) { + /* interpret a size of 0x0 as indication to quit VirtualBox */ + if (_iconsole->PowerButton() != S_OK) + Genode::error("ACPI shutdown failed"); + return; + } + + _idisplay->SetVideoModeHint(0 /*=display*/, + true /*=enabled*/, false /*=changeOrigin*/, + 0 /*=originX*/, 0 /*=originY*/, + fb->w(), fb->h(), + 32, true); + }); + }); +} + + void Main::handle_vbox_event(VBoxEventType_T ev_type, IEvent &ev) { switch (ev_type) {