vbox6: support dynamic framebuffer resolution

Issue #4031
This commit is contained in:
Christian Helmuth 2021-08-17 15:26:18 +02:00
parent 50cc51f132
commit a6fb61dbf2
2 changed files with 45 additions and 7 deletions

View File

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

View File

@ -265,6 +265,10 @@ struct Main : Event_handler
void _handle_input();
Signal_handler<Main> _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::Connection>(_gui_connections, _env);
String<3> label { i };
Gui::Connection &gui = *new Registered<Gui::Connection>(_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<Genodefb *>(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) {