mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 10:46:25 +00:00
parent
cb3b6c4b88
commit
61454178c0
@ -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>(Control_header::Type::OK_DISPLAY_INFO);
|
||||
|
||||
dir.write<Display_info_response::X>(0);
|
||||
dir.write<Display_info_response::Y>(0);
|
||||
dir.write<Display_info_response::Width>(_device._fb_mode.area.w());
|
||||
dir.write<Display_info_response::Height>(_device._fb_mode.area.h());
|
||||
dir.write<Display_info_response::Width>(mode.area.w());
|
||||
dir.write<Display_info_response::Height>(mode.area.h());
|
||||
dir.write<Display_info_response::Enabled>(1);
|
||||
dir.write<Display_info_response::Flags>(0);
|
||||
}
|
||||
@ -182,6 +183,9 @@ void Vmm::Virtio_gpu_control_request::_resource_flush()
|
||||
uint32_t id = rf.read<Resource_flush::Resource_id>();
|
||||
response.write<Control_header::Type>(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<Resource_flush::X>();
|
||||
uint32_t y = rf.read<Resource_flush::Y>();
|
||||
uint32_t w = rf.read<Resource_flush::Width>();
|
||||
uint32_t h = rf.read<Resource_flush::Height>();
|
||||
uint32_t w = min(rf.read<Resource_flush::Width>(),
|
||||
_device._fb_mode.area.w() - x);
|
||||
uint32_t h = min(rf.read<Resource_flush::Height>(),
|
||||
_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>(Control_header::Type::ERR_INVALID_PARAMETER);
|
||||
return;
|
||||
}
|
||||
|
||||
enum { BYTES_PER_PIXEL = Virtio_gpu_device::BYTES_PER_PIXEL };
|
||||
response.write<Control_header::Type>(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<void>() +
|
||||
(_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);
|
||||
});
|
||||
}
|
||||
|
@ -311,7 +311,6 @@ class Vmm::Virtio_gpu_device : public Virtio_device<Virtio_gpu_queue, 2>
|
||||
Constructible<Attached_dataspace> _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<Virtio_gpu_queue, 2>
|
||||
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<Virtio_gpu_queue, 2>
|
||||
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<Command::Geometry>(_view, Rect(Point(0, 0), _fb_mode.area));
|
||||
_gui.enqueue<Command::To_front>(_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<Virtio_gpu_queue, 2>
|
||||
_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<Command::Geometry>(_view, Rect(Point(0, 0), _fb_mode.area));
|
||||
_gui.enqueue<Command::To_front>(_view, Gui::Session::View_handle());
|
||||
_gui.execute();
|
||||
return _gui.mode();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _VIRTIO_GPU_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user