From dd4a3b02631a87d66536f9f10d9031d7e5a22867 Mon Sep 17 00:00:00 2001 From: Christian Helmuth Date: Mon, 24 Aug 2020 15:15:40 +0200 Subject: [PATCH] vbox: direct screen updates via NotifyUpdate() --- repos/ports/src/virtualbox5/frontend/fb.h | 82 ++++++++++++++++---- repos/ports/src/virtualbox5/frontend/main.cc | 2 +- 2 files changed, 70 insertions(+), 14 deletions(-) diff --git a/repos/ports/src/virtualbox5/frontend/fb.h b/repos/ports/src/virtualbox5/frontend/fb.h index 5a8bc15c3e..302c826010 100644 --- a/repos/ports/src/virtualbox5/frontend/fb.h +++ b/repos/ports/src/virtualbox5/frontend/fb.h @@ -24,6 +24,7 @@ #include "Global.h" #include "VirtualBoxBase.h" +#include "DisplayWrap.h" typedef Gui::Session::View_handle View_handle; @@ -47,6 +48,9 @@ class Genodefb : void *_fb_base; RTCRITSECT _fb_lock; + ComPtr _display; + ComPtr _display_bitmap; + void _clear_screen() { if (!_fb_base) return; @@ -85,13 +89,14 @@ class Genodefb : public: - Genodefb (Genode::Env &env, Gui::Connection &gui) + Genodefb (Genode::Env &env, Gui::Connection &gui, ComPtr const &display) : _env(env), _gui(gui), _fb(*gui.framebuffer()), _virtual_fb_mode(_initial_setup()), - _fb_base(env.rm().attach(_fb.dataspace())) + _fb_base(env.rm().attach(_fb.dataspace())), + _display(display) { int rc = RTCritSectInit(&_fb_lock); Assert(rc == VINF_SUCCESS); @@ -137,6 +142,9 @@ class Genodefb : Lock(); + /* 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()); @@ -155,14 +163,18 @@ class Genodefb : _virtual_fb_mode = Fb_Genode::Mode { .area = { w, h } }; result = S_OK; - } else + } else { Genode::log("fb resize : [", screen, "] ", _virtual_fb_mode.area, " -> ", w, "x", h, " ignored" " (host: ", _fb_mode.area, ")"); + } Unlock(); + /* request appropriate NotifyUpdate() */ + _display->InvalidateAndUpdateScreen(screen); + return result; } @@ -171,12 +183,6 @@ class Genodefb : if (ComSafeArrayOutIsNull(enmCapabilities)) return E_POINTER; - com::SafeArray caps; - caps.resize(1); - caps[0] = FramebufferCapabilities_UpdateImage; - //caps[0] = FramebufferCapabilities_VHWA; - caps.detachTo(ComSafeArrayOutArg(enmCapabilities)); - return S_OK; } @@ -189,6 +195,60 @@ class Genodefb : return S_OK; } + HRESULT NotifyUpdate(ULONG o_x, ULONG o_y, ULONG width, ULONG height) override + { + if (!_fb_base) return S_OK; + + Lock(); + + if (_display_bitmap.isNull()) { + _clear_screen(); + Unlock(); + return S_OK; + } + + BYTE *pAddress = NULL; + ULONG ulWidth = 0; + ULONG ulHeight = 0; + ULONG ulBitsPerPixel = 0; + ULONG ulBytesPerLine = 0; + BitmapFormat_T bitmapFormat = BitmapFormat_Opaque; + _display_bitmap->QueryBitmapInfo(&pAddress, + &ulWidth, + &ulHeight, + &ulBitsPerPixel, + &ulBytesPerLine, + &bitmapFormat); + + Gui::Area const area_fb = Gui::Area(_fb_mode.area.w(), + _fb_mode.area.h()); + Gui::Area const area_vm = Gui::Area(ulWidth, ulHeight); + + using namespace Genode; + + typedef Pixel_rgb888 Pixel_src; + typedef Pixel_rgb888 Pixel_dst; + + Texture texture((Pixel_src *)pAddress, nullptr, area_vm); + Surface surface((Pixel_dst *)_fb_base, area_fb); + + surface.clip(Surface_base::Rect(Surface_base::Point(o_x, o_y), + Surface_base::Area(width, height))); + + Texture_painter::paint(surface, + texture, + Genode::Color(0, 0, 0), + Surface_base::Point(0, 0), + Texture_painter::SOLID, + false); + + _fb.refresh(o_x, o_y, width, height); + + Unlock(); + + return S_OK; + } + STDMETHODIMP NotifyUpdateImage(PRUint32 o_x, PRUint32 o_y, PRUint32 width, PRUint32 height, PRUint32 imageSize, @@ -263,10 +323,6 @@ class Genodefb : Assert(!"FixMe"); return E_NOTIMPL; } - HRESULT NotifyUpdate(ULONG x, ULONG y, ULONG w, ULONG h) override { - Assert(!"FixMe"); - return E_NOTIMPL; } - STDMETHODIMP COMGETTER(BitsPerPixel)(ULONG *bits) override { Assert(!"FixMe"); return E_NOTIMPL; } diff --git a/repos/ports/src/virtualbox5/frontend/main.cc b/repos/ports/src/virtualbox5/frontend/main.cc index 2c4f1a9c93..5594a01a7c 100644 --- a/repos/ports/src/virtualbox5/frontend/main.cc +++ b/repos/ports/src/virtualbox5/frontend/main.cc @@ -169,7 +169,7 @@ HRESULT setupmachine(Genode::Env &env) for (unsigned uScreenId = 0; uScreenId < cMonitors; uScreenId++) { - Genodefb *fb = new Genodefb(env, genodeConsole->gui()); + Genodefb *fb = new Genodefb(env, genodeConsole->gui(), display); HRESULT rc = display->AttachFramebuffer(uScreenId, fb, gaFramebufferId[uScreenId].asOutParam()); if (FAILED(rc)) return rc;