diff --git a/repos/os/src/server/vmm/virtio_gpu.cc b/repos/os/src/server/vmm/virtio_gpu.cc index 4f937f6d94..0a1099f969 100644 --- a/repos/os/src/server/vmm/virtio_gpu.cc +++ b/repos/os/src/server/vmm/virtio_gpu.cc @@ -43,14 +43,15 @@ void Vmm::Virtio_gpu_queue::notify(Virtio_gpu_device & dev) void Vmm::Virtio_gpu_control_request::_get_display_info() { + Framebuffer::Mode mode = _device.resize(); Display_info_response dir { _desc_addr(1) }; memset((void*)dir.base(), 0, Display_info_response::SIZE); dir.write(Control_header::Type::OK_DISPLAY_INFO); dir.write(0); dir.write(0); - dir.write(_device._fb_mode.area.w()); - dir.write(_device._fb_mode.area.h()); + dir.write(mode.area.w()); + dir.write(mode.area.h()); dir.write(1); dir.write(0); } @@ -182,6 +183,9 @@ void Vmm::Virtio_gpu_control_request::_resource_flush() uint32_t id = rf.read(); response.write(Control_header::Type::ERR_INVALID_RESOURCE_ID); + if (!_device._fb_ds.constructed()) + return; + using Resource = Virtio_gpu_device::Resource; _device._resources.for_each([&] (Resource & res) { if (res.id != id) @@ -189,20 +193,23 @@ void Vmm::Virtio_gpu_control_request::_resource_flush() uint32_t x = rf.read(); uint32_t y = rf.read(); - uint32_t w = rf.read(); - uint32_t h = rf.read(); + uint32_t w = min(rf.read(), + _device._fb_mode.area.w() - x); + uint32_t h = min(rf.read(), + _device._fb_mode.area.h() - y); - if (x > res.area.w() || - y > res.area.h() || - w > res.area.w() || - h > res.area.h() || - x + w > res.area.w() || + enum { BYTES_PER_PIXEL = Virtio_gpu_device::BYTES_PER_PIXEL }; + + if (x > res.area.w() || + y > res.area.h() || + w > res.area.w() || + h > res.area.h() || + x + w > res.area.w() || y + h > res.area.h()) { response.write(Control_header::Type::ERR_INVALID_PARAMETER); return; } - enum { BYTES_PER_PIXEL = Virtio_gpu_device::BYTES_PER_PIXEL }; response.write(Control_header::Type::OK_NO_DATA); void * src = @@ -211,10 +218,10 @@ void Vmm::Virtio_gpu_control_request::_resource_flush() void * dst = (void*)((addr_t)_device._fb_ds->local_addr() + (_device._fb_mode.area.w() * y + x) * BYTES_PER_PIXEL); - uint32_t line = res.area.w() * BYTES_PER_PIXEL; - - blit(src, line, dst, line, w*BYTES_PER_PIXEL, h); + uint32_t line_src = res.area.w() * BYTES_PER_PIXEL; + uint32_t line_dst = _device._fb_mode.area.w() * BYTES_PER_PIXEL; + blit(src, line_src, dst, line_dst, w*BYTES_PER_PIXEL, h); _device._gui.framebuffer()->refresh(x, y, w, h); }); } diff --git a/repos/os/src/server/vmm/virtio_gpu.h b/repos/os/src/server/vmm/virtio_gpu.h index e9effa52ea..bded8e8cda 100644 --- a/repos/os/src/server/vmm/virtio_gpu.h +++ b/repos/os/src/server/vmm/virtio_gpu.h @@ -311,7 +311,6 @@ class Vmm::Virtio_gpu_device : public Virtio_device Constructible _fb_ds { }; Framebuffer::Mode _fb_mode { _gui.mode() }; Gui::Session::View_handle _view = _gui.create_view(); - bool _mode_changed { true }; using Area = Genode::Area<>; using Rect = Genode::Rect<>; @@ -390,25 +389,25 @@ class Vmm::Virtio_gpu_device : public Virtio_device enum { EVENTS_READ = 0, EVENTS_CLEAR = 4, - SCANOUTS = 8 }; + SCANOUTS = 8, + NUM_CAPSETS = 12 + }; + + enum Events { NONE = 0, DISPLAY = 1 }; Register read(Address_range & range, Cpu&) override { - if (range.start() == EVENTS_READ && range.size() == 4) - return dev._mode_changed ? 1 : 0; + if (range.start() == EVENTS_READ) + return DISPLAY; /* we support no multi-head, just return 1 */ - if (range.start() == SCANOUTS && range.size() == 4) + if (range.start() == SCANOUTS) return 1; return 0; } - void write(Address_range & range, Cpu&, Register v) override - { - if (range.start() == EVENTS_CLEAR && range.size() == 4 && v == 1) - dev._mode_changed = false; - } + void write(Address_range &, Cpu&, Register) override {} Configuration_area(Virtio_gpu_device & device) : @@ -420,21 +419,7 @@ class Vmm::Virtio_gpu_device : public Virtio_device void _mode_change() { Genode::Mutex::Guard guard(_mutex); - - _fb_mode = _gui.mode(); - - _gui.buffer(_fb_mode, false); - - if (_fb_mode.area.count() > 0) - _fb_ds.construct(_env.rm(), - _gui.framebuffer()->dataspace()); - - using Command = Gui::Session::Command; - _gui.enqueue(_view, Rect(Point(0, 0), _fb_mode.area)); - _gui.enqueue(_view, Gui::Session::View_handle()); - _gui.execute(); - - _mode_changed = true; + _config_notification(); } void _notify(unsigned idx) override @@ -466,13 +451,30 @@ class Vmm::Virtio_gpu_device : public Virtio_device _handler(cpu, env.ep(), *this, &Virtio_gpu_device::_mode_change) { _gui.mode_sigh(_handler); - _mode_change(); } void buffer_notification() { _buffer_notification(); } + + Framebuffer::Mode resize() + { + _fb_ds.destruct(); + + _fb_mode = _gui.mode(); + _gui.buffer(_fb_mode, false); + + if (_fb_mode.area.count() > 0) + _fb_ds.construct(_env.rm(), + _gui.framebuffer()->dataspace()); + + using Command = Gui::Session::Command; + _gui.enqueue(_view, Rect(Point(0, 0), _fb_mode.area)); + _gui.enqueue(_view, Gui::Session::View_handle()); + _gui.execute(); + return _gui.mode(); + } }; #endif /* _VIRTIO_GPU_H_ */