vbox: enable video acceleration (VBVA)

This commit enables the VirtualBox graphics adapter, provides guest mouse
pointer integration with Nitpicker using the 'vbox_pointer' application
and enhances the VirtualBox run scripts with the configuration of
Nitpicker, input merger and network driver.

Fixes #1474
This commit is contained in:
Christian Prochaska 2015-03-30 18:00:43 +02:00 committed by Norman Feske
parent 0ef20f7ece
commit af2cd7175c
17 changed files with 1344 additions and 481 deletions

View File

@ -0,0 +1,75 @@
/*
* \brief Functor for converting pixel formats by applying dithering
* \author Norman Feske
* \date 2014-09-10
*/
/*
* Copyright (C) 2014 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _DITHER_PAINTER_H_
#define _DITHER_PAINTER_H_
#include <util/dither_matrix.h>
#include <os/surface.h>
struct Dither_painter
{
/*
* Surface and texture must have the same size
*/
template <typename DST_PT, typename SRC_PT>
static inline void paint(Genode::Surface<DST_PT> &surface,
Genode::Texture<SRC_PT> const &texture)
{
if (surface.size() != texture.size()) return;
Genode::Surface_base::Rect const clipped = surface.clip();
if (!clipped.valid()) return;
unsigned const offset = surface.size().w()*clipped.y1() + clipped.x1();
DST_PT *dst, *dst_line = surface.addr() + offset;
SRC_PT const *src_pixel, *src_pixel_line = texture.pixel() + offset;
unsigned char const *src_alpha, *src_alpha_line = texture.alpha() + offset;
unsigned const line_len = surface.size().w();
for (int y = clipped.y1(), h = clipped.h() ; h--; y++) {
src_pixel = src_pixel_line;
src_alpha = src_alpha_line;
dst = dst_line;
for (int x = clipped.x1(), w = clipped.w(); w--; x++) {
int const v = Genode::Dither_matrix::value(x, y) >> 4;
SRC_PT const pixel = *src_pixel++;
unsigned char const alpha = *src_alpha++;
int const r = pixel.r() - v;
int const g = pixel.g() - v;
int const b = pixel.b() - v;
int const a = alpha ? (int)alpha - v : 0;
using Genode::min;
using Genode::max;
*dst++ = DST_PT(max(0, r), max(0, g), max(0, b), max(0, a));
}
src_pixel_line += line_len;
src_alpha_line += line_len;
dst_line += line_len;
}
}
};
#endif /* _DITHER_PAINTER_H_ */

View File

@ -0,0 +1,38 @@
/*
* \brief shape report
* \author Christian Prochaska
* \date 2015-03-20
*/
/*
* Copyright (C) 2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__VBOX_POINTER__SHAPE_REPORT_H_
#define _INCLUDE__VBOX_POINTER__SHAPE_REPORT_H_
namespace Vbox_pointer {
enum {
MAX_WIDTH = 100,
MAX_HEIGHT = 100,
MAX_SHAPE_SIZE = MAX_WIDTH*MAX_HEIGHT*4
};
struct Shape_report;
}
struct Vbox_pointer::Shape_report
{
bool visible;
unsigned int x_hot;
unsigned int y_hot;
unsigned int width;
unsigned int height;
unsigned char shape[MAX_SHAPE_SIZE];
};
#endif /* _INCLUDE__VBOX_POINTER__SHAPE_REPORT_H_ */

View File

@ -1 +1 @@
7e0d7dd26169ee60eea603a22fd068bd0b879a79
1e49158411c029263f5b29b890ec3f212b2caf29

View File

@ -8,7 +8,7 @@ URL(virtualbox) := http://download.virtualbox.org/virtualbox/$(VERSION)/$(VIRTUA
DIR(virtualbox) := src/app/virtualbox
SHA(virtualbox) := e4c23b713e8715b8e0172fa066f2197756e901fe
PATCHES_LIST := acpi_drv dev_e1000 eminternal fake_pci_vendor iconv mouse
PATCHES_LIST := acpi_drv dev_e1000 eminternal iconv mouse
PATCHES_LIST += pdm_driver poke sharedfolder_pagelist
PATCHES_LIST += time-log-deadlock tm_retries vbox_inc vbox_main network
PATCHES_LIST += vga_fb vga_vbva vmdk vmmdev avoid_yield serial rem_irq usb

View File

@ -7,7 +7,7 @@ set flavor "win7"
# Write overlay back to harddisk if set to 0
set use_ram_fs 0
set use_usb 0
set use_usb 1
set use_ps2 [have_spec ps2]
source ${genode_dir}/repos/ports/run/vbox_win.inc

View File

@ -102,7 +102,7 @@ catch { exec dd if=/dev/urandom of=bin/test.bin bs=4096 count=8160 }
# Step 1: prepare and start the actual VM
#
set build_components {
server/ram_fs
server/ram_fs server/report_rom
server/tcp_terminal drivers/nic
lib/libc_noux
noux/minimal
@ -117,7 +117,7 @@ foreach pkg {bash coreutils} {
set boot_modules {
ram_fs
noux libc_noux.lib.so bash.tar coreutils.tar
tcp_terminal lwip.lib.so nic_drv
tcp_terminal lwip.lib.so nic_drv report_rom
test.bin template.bat
vm_auto_share.vbox
}
@ -189,6 +189,12 @@ set config_of_app {
</config>
</start>
<start name="report_rom">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Report"/> <service name="ROM"/> </provides>
<config> <rom /> </config>
</start>
<start name="vbox" priority="-2">
<binary name="virtualbox" />
<resource name="RAM" quantum="1280M"/>

View File

@ -9,7 +9,7 @@ set flavor "win8"
# Write overlay back to harddisk if set to 0
set use_ram_fs 0
set use_usb 0
set use_usb 1
set use_ps2 [have_spec ps2]
source ${genode_dir}/repos/ports/run/vbox_win.inc

View File

@ -10,10 +10,120 @@ set vdi_image "${flavor}.vdi"
set vbox_file "vm_${flavor}.vbox"
set overlay_image "overlay_${flavor}.vdi"
set build_components { }
set boot_modules { }
set build_components {
server/input_merger
drivers/nic
server/nitpicker
app/vbox_pointer
server/nit_fb
server/report_rom
}
set boot_modules {
input_merger
nic_drv
nitpicker
vbox_pointer
nit_fb
report_rom
}
set config_of_app {
<start name="input_merger">
<resource name="RAM" quantum="1M" />
<provides>
<service name="Input" />
</provides>
<config>}
append_if [expr $use_ps2] config_of_app {
<input label="ps2" /> }
append_if [expr $use_usb] config_of_app {
<input label="usb_hid" />}
append config_of_app {
</config>
<route> }
append_if [expr $use_ps2] config_of_app {
<service name="Input">
<if-arg key="label" value="ps2" /> <child name="ps2_drv" />
</service> }
append_if [expr $use_usb] config_of_app {
<service name="Input">
<if-arg key="label" value="usb_hid" /> <child name="usb_drv" />
</service> }
append config_of_app {
<any-service> <parent /> <any-child /> </any-service>
</route>
</start>
<!--
Note: to get network access in the VM, the virtual network adapter
needs to be enabled in the .vbox file (disabled by default)
-->
<start name="nic_drv" priority="-1">
<resource name="RAM" quantum="8M" />
<provides>
<service name="Nic" />
</provides>
</start>
<start name="report_rom">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Report"/> <service name="ROM"/> </provides>
<config>
<rom>
<policy label="vbox_pointer -> hover" report="nitpicker -> hover"/>
<policy label="vbox_pointer -> xray" report="nitpicker -> xray"/>
<policy label="vbox_pointer -> shape" report="vbox -> shape"/>
</rom>
</config>
</start>
<start name="nitpicker" priority="-1">
<resource name="RAM" quantum="2M"/>
<provides><service name="Nitpicker"/></provides>
<route>
<service name="Framebuffer"> <child name="fb_drv" /> </service>
<service name="Input"> <child name="input_merger" /> </service>
<any-service> <parent/> <any-child /> </any-service>
</route>
<config>
<report focus="yes" hover="yes" xray="yes" />
<domain name="pointer" layer="1" xray="no" origin="pointer" />
<domain name="vbox" layer="2" />
<domain name="" layer="2" />
<policy label="vbox_pointer" domain="pointer"/>
<policy label="nit_fb" domain="vbox"/>
<policy label="" domain=""/>
<global-key name="KEY_SCROLLLOCK" operation="xray" />
<global-key name="KEY_SYSRQ" operation="kill" />
<global-key name="KEY_PRINT" operation="kill" />
<global-key name="KEY_F11" operation="kill" />
<global-key name="KEY_F12" operation="xray" />
</config>
</start>
<start name="vbox_pointer" priority="-1">
<resource name="RAM" quantum="1M"/>
<route>
<service name="Nitpicker"> <child name="nitpicker"/> </service>
<service name="ROM"> <child name="report_rom"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="nit_fb" priority="-1">
<resource name="RAM" quantum="8M" />
<provides>
<service name="Framebuffer" />
<service name="Input" />
</provides>
<config width="1024" height="768" />
</start>
<start name="vbox" priority="-2">
<binary name="virtualbox" />
<resource name="RAM" quantum="1280M"/>}
@ -44,6 +154,8 @@ append_if [expr $use_ram_fs] config_of_app {
append config_of_app {
<service name="File_system"> <child name="rump_fs"/> </service>
<service name="Framebuffer"> <child name="nit_fb" /> </service>
<service name="Input"> <child name="nit_fb" /> </service>
<any-service> <parent/> <any-child /> </any-service>
</route>
</start>

View File

@ -41,7 +41,7 @@ set config {
<service name="SIGNAL"/>
</parent-provides>
<default-route>
<any-service> <any-child/> <parent/> </any-service>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<start name="timer">
<resource name="RAM" quantum="1M"/>
@ -139,7 +139,7 @@ append_if [have_spec framebuffer] config {
<start name="fb_drv" priority="-1">
<resource name="RAM" quantum="6M"/>
<provides><service name="Framebuffer"/></provides>
<config buffered="yes" width="1024" height="768" depth="16" />
<config buffered="yes" />
</start>}
append_if [have_spec x86] config {

View File

@ -0,0 +1,36 @@
/*
* \brief Mouse cursor pixel data
* \author Norman Feske
* \date 2006-08-09
*/
/*
* Copyright (C) 2006-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
static struct {
unsigned short w, h, pixels[16][16];
} big_mouse = {
16,16,
{
{0x738E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},
{0x0000,0x94B2,0x7BCF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},
{0x0000,0x630C,0xC638,0xC638,0x6B4D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},
{0x0000,0x0000,0x738E,0x8C71,0xFFFF,0xB5B6,0x6B4D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},
{0x0000,0x0000,0x630C,0x4A49,0x630C,0xB5B6,0xFFFF,0xB5B6,0x630C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},
{0x0000,0x0000,0x0000,0x528A,0x528A,0x630C,0x9492,0xB5B6,0xFFFF,0xB5B6,0x630C,0x0000,0x0000,0x0000,0x0000,0x0000},
{0x0000,0x0000,0x0000,0x528A,0x39C7,0x4208,0x630C,0x7BCF,0xB5B6,0xFFFF,0xFFFF,0xB5B6,0x630C,0x0000,0x0000,0x0000},
{0x0000,0x0000,0x0000,0x0000,0x4208,0x39C7,0x4208,0x630C,0x7BCF,0xB5B6,0xDEFB,0xFFFF,0xFFFF,0xB5B6,0x630C,0x0000},
{0x0000,0x0000,0x0000,0x0000,0x4A49,0x1082,0x39C7,0x4208,0x5ACB,0x7BCF,0x8C71,0xAD75,0x630C,0x0000,0x0000,0x0000},
{0x0000,0x0000,0x0000,0x0000,0x0000,0x4208,0x1082,0x39C7,0x5ACB,0x630C,0xB5B6,0x0000,0x0000,0x0000,0x0000,0x0000},
{0x0000,0x0000,0x0000,0x0000,0x0000,0x4A49,0x1082,0x1082,0x39C7,0x4A49,0x630C,0xAD75,0x0000,0x0000,0x0000,0x0000},
{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x4208,0x1082,0x4A49,0x0000,0x4A49,0x630C,0x8C71,0x0000,0x0000,0x0000},
{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x4A49,0x39C7,0x4A49,0x0000,0x0000,0x4A49,0x630C,0x8C71,0x0000,0x0000},
{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x4A49,0x0000,0x0000,0x0000,0x0000,0x4A49,0x630C,0x8C71,0x0000},
{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x4A49,0x0000,0x0000,0x0000,0x0000,0x0000,0x4A49,0x4A49,0x0000},
{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},
}
};

View File

@ -0,0 +1,410 @@
/*
* \brief Nitpicker pointer with support for VirtualBox-defined shapes
* \author Norman Feske
* \author Christian Helmuth
* \author Christian Prochaska
* \date 2014-07-02
*/
/*
* Copyright (C) 2014-2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <base/sleep.h>
#include <os/attached_dataspace.h>
#include <os/attached_ram_dataspace.h>
#include <os/attached_rom_dataspace.h>
#include <os/surface.h>
#include <os/pixel_alpha8.h>
#include <os/pixel_rgb565.h>
#include <os/pixel_rgb888.h>
#include <os/texture_rgb888.h>
#include <os/texture.h>
#include <util/xml_node.h>
#include <nitpicker_session/connection.h>
#include <vbox_pointer/dither_painter.h>
#include <vbox_pointer/shape_report.h>
/* local includes */
#include "big_mouse.h"
/* exception */
struct Pointer_shape_too_large { };
template <typename PT>
void convert_default_cursor_data_to_pixels(PT *pixel, Nitpicker::Area size)
{
unsigned char *alpha = (unsigned char *)(pixel + size.count());
for (unsigned y = 0; y < size.h(); y++) {
for (unsigned x = 0; x < size.w(); x++) {
/* the source is known to be in RGB565 format */
Genode::Pixel_rgb565 src =
*(Genode::Pixel_rgb565 *)(&big_mouse.pixels[y][x]);
unsigned const i = y*size.w() + x;
pixel[i] = PT(src.r(), src.g(), src.b());
alpha[i] = src.r() ? 255 : 0;
}
}
}
template <typename PT>
void convert_vbox_cursor_data_to_pixels(PT *pixel, unsigned char *shape,
Nitpicker::Area size)
{
Genode::Attached_ram_dataspace texture_pixel_ds { Genode::env()->ram_session(),
size.count() *
sizeof(Genode::Pixel_rgb888) };
Genode::Attached_ram_dataspace texture_alpha_ds { Genode::env()->ram_session(),
size.count() };
Genode::Texture<Genode::Pixel_rgb888>
texture(texture_pixel_ds.local_addr<Genode::Pixel_rgb888>(),
texture_alpha_ds.local_addr<unsigned char>(),
size);
for (unsigned int y = 0; y < size.h(); y++) {
/* convert the shape data from BGRA encoding to RGBA encoding */
unsigned char *bgra_line = &shape[y * size.w() * 4];
unsigned char rgba_line[size.w() * 4];
for (unsigned int i = 0; i < size.w() * 4; i += 4) {
rgba_line[i + 0] = bgra_line[i + 2];
rgba_line[i + 1] = bgra_line[i + 1];
rgba_line[i + 2] = bgra_line[i + 0];
rgba_line[i + 3] = bgra_line[i + 3];
}
/* import the RGBA-encoded line into the texture */
texture.rgba(rgba_line, size.w(), y);
}
Genode::Pixel_alpha8 *alpha =
reinterpret_cast<Genode::Pixel_alpha8*>(pixel + size.count());
Genode::Surface<PT> pixel_surface(pixel, size);
Genode::Surface<Genode::Pixel_alpha8> alpha_surface(alpha, size);
Dither_painter::paint(pixel_surface, texture);
Dither_painter::paint(alpha_surface, texture);
}
//struct Log { Log(char const *msg) { PINF("Log: %s", msg); } };
typedef Genode::String<64> Domain_name;
class Domain : public Genode::List<Domain>::Element
{
public:
struct Name_too_long { };
private:
Domain_name _name;
public:
Domain(char const *name) : _name(name)
{
if (Genode::strlen(name) + 1 > _name.capacity())
throw Name_too_long();
}
Domain_name const & name() { return _name; }
};
struct Domain_list : private Genode::List<Domain>
{
void add(char const *name)
{
Domain *d = new (Genode::env()->heap()) Domain(name);
insert(d);
}
bool contains(Domain_name const &name)
{
for (Domain *d = first(); d; d = d->next())
if (d->name() == name)
return true;
return false;
}
};
struct Main
{
Genode::Attached_rom_dataspace hover_ds { "hover" };
Genode::Attached_rom_dataspace xray_ds { "xray" };
Genode::Attached_rom_dataspace shape_ds { "shape" };
Genode::Signal_receiver sig_rec;
void handle_hover(unsigned num = 0);
void handle_xray(unsigned num = 0);
void handle_shape(unsigned num = 0);
Genode::Signal_dispatcher<Main> hover_signal_dispatcher {
sig_rec, *this, &Main::handle_hover };
Genode::Signal_dispatcher<Main> xray_signal_dispatcher {
sig_rec, *this, &Main::handle_xray };
Genode::Signal_dispatcher<Main> shape_signal_dispatcher {
sig_rec, *this, &Main::handle_shape };
Nitpicker::Connection nitpicker;
Nitpicker::Session::View_handle view = nitpicker.create_view();
Domain_list vbox_domains;
Domain_name current_domain;
bool xray = false;
bool default_pointer_visible = false;
bool vbox_pointer_visible = false;
bool vbox_pointer_shape_changed = false;
Nitpicker::Area current_cursor_size;
Genode::Dataspace_capability pointer_ds;
void resize_nitpicker_buffer_if_needed(Nitpicker::Area cursor_size)
{
if (cursor_size != current_cursor_size) {
Framebuffer::Mode const mode { (int)cursor_size.w(), (int)cursor_size.h(),
Framebuffer::Mode::RGB565 };
nitpicker.buffer(mode, true /* use alpha */);
pointer_ds = nitpicker.framebuffer()->dataspace();
current_cursor_size = cursor_size;
}
}
void show_default_pointer()
{
if (!default_pointer_visible) {
Nitpicker::Area const cursor_size { big_mouse.w, big_mouse.h };
try {
resize_nitpicker_buffer_if_needed(cursor_size);
} catch (...) {
PERR("%s: could not resize the pointer buffer for %u x %u pixels",
__func__, cursor_size.w(), cursor_size.h());
return;
}
Genode::Attached_dataspace ds { pointer_ds };
convert_default_cursor_data_to_pixels(ds.local_addr<Genode::Pixel_rgb565>(),
cursor_size);
nitpicker.framebuffer()->refresh(0, 0, cursor_size.w(), cursor_size.h());
Nitpicker::Rect geometry(Nitpicker::Point(0, 0), cursor_size);
nitpicker.enqueue<Nitpicker::Session::Command::Geometry>(view, geometry);
nitpicker.execute();
default_pointer_visible = true;
vbox_pointer_visible = false;
}
}
void show_vbox_pointer()
{
if (!vbox_pointer_visible || vbox_pointer_shape_changed) {
try {
Vbox_pointer::Shape_report *shape_report =
shape_ds.local_addr<Vbox_pointer::Shape_report>();
if (shape_report->visible) {
if ((shape_report->width == 0) || (shape_report->height == 0))
return;
if ((shape_report->width > Vbox_pointer::MAX_WIDTH) ||
(shape_report->height > Vbox_pointer::MAX_HEIGHT))
throw Pointer_shape_too_large();
Nitpicker::Area const cursor_size { shape_report->width,
shape_report->height };
resize_nitpicker_buffer_if_needed(cursor_size);
Genode::Attached_dataspace ds { pointer_ds };
convert_vbox_cursor_data_to_pixels(ds.local_addr<Genode::Pixel_rgb565>(),
shape_report->shape,
cursor_size);
nitpicker.framebuffer()->refresh(0, 0, cursor_size.w(), cursor_size.h());
Nitpicker::Rect geometry(Nitpicker::Point(-shape_report->x_hot, -shape_report->y_hot), cursor_size);
nitpicker.enqueue<Nitpicker::Session::Command::Geometry>(view, geometry);
} else {
Nitpicker::Rect geometry(Nitpicker::Point(0, 0), Nitpicker::Area(0, 0));
nitpicker.enqueue<Nitpicker::Session::Command::Geometry>(view, geometry);
}
} catch (Genode::Volatile_object<Genode::Attached_dataspace>::Deref_unconstructed_object) {
/* no shape has been reported, yet */
Nitpicker::Rect geometry(Nitpicker::Point(0, 0), Nitpicker::Area(0, 0));
nitpicker.enqueue<Nitpicker::Session::Command::Geometry>(view, geometry);
}
nitpicker.execute();
vbox_pointer_visible = true;
vbox_pointer_shape_changed = false;
default_pointer_visible = false;
}
}
void update_pointer()
{
if (xray || !vbox_domains.contains(current_domain))
show_default_pointer();
else
try {
show_vbox_pointer();
} catch (Pointer_shape_too_large) {
PERR("%s: the pointer shape is larger than the maximum supported size of %u x %u",
__func__, Vbox_pointer::MAX_WIDTH, Vbox_pointer::MAX_HEIGHT);
show_default_pointer();
} catch (...) {
PERR("%s: an unhandled exception occurred while trying to show \
the VirtualBox pointer", __func__);
show_default_pointer();
}
}
Main()
{
/*
* Try to allocate the Nitpicker buffer for the maximum supported
* pointer size to let the user know right from the start if the
* RAM quota is too low.
*/
Framebuffer::Mode const mode { Vbox_pointer::MAX_WIDTH, Vbox_pointer::MAX_HEIGHT,
Framebuffer::Mode::RGB565 };
nitpicker.buffer(mode, true /* use alpha */);
/* TODO should be read from config */
vbox_domains.add("vbox");
/* register signal handlers */
hover_ds.sigh(hover_signal_dispatcher);
xray_ds.sigh(xray_signal_dispatcher);
shape_ds.sigh(shape_signal_dispatcher);
nitpicker.enqueue<Nitpicker::Session::Command::To_front>(view);
nitpicker.execute();
/* import initial state */
handle_hover();
handle_xray();
handle_shape();
}
};
static Domain_name read_string_attribute(Genode::Xml_node const &node,
char const *attr,
Domain_name const &default_value)
{
try {
char buf[Domain_name::capacity()];
node.attribute(attr).value(buf, sizeof(buf));
return Domain_name(buf);
}
catch (...) {
return default_value; }
}
void Main::handle_hover(unsigned)
{
hover_ds.update();
if (!hover_ds.is_valid())
return;
/* read new hover information from nitpicker's hover report */
try {
Genode::Xml_node node(hover_ds.local_addr<char>());
current_domain = read_string_attribute(node, "domain", Domain_name());
}
catch (...) {
PWRN("could not parse hover report");
}
update_pointer();
}
void Main::handle_xray(unsigned)
{
xray_ds.update();
if (!xray_ds.is_valid())
return;
try {
Genode::Xml_node node(xray_ds.local_addr<char>());
xray = node.has_attribute("enabled")
&& node.attribute("enabled").has_value("yes");
}
catch (...) {
PWRN("could not parse xray report");
}
update_pointer();
}
void Main::handle_shape(unsigned)
{
shape_ds.update();
if (!shape_ds.is_valid())
return;
if (shape_ds.size() < sizeof(Vbox_pointer::Shape_report))
return;
vbox_pointer_shape_changed = true;
update_pointer();
}
int main()
{
static Main main;
/* dispatch signals */
for (;;) {
Genode::Signal sig = main.sig_rec.wait_for_signal();
Genode::Signal_dispatcher_base *dispatcher =
dynamic_cast<Genode::Signal_dispatcher_base *>(sig.context());
if (dispatcher)
dispatcher->dispatch(sig.num());
}
}

View File

@ -0,0 +1,3 @@
TARGET = vbox_pointer
SRC_CC = main.cc
LIBS += base

View File

@ -86,12 +86,9 @@ HRESULT Console::Teleport(unsigned short*, unsigned int, unsigned short*,
unsigned int, Progress**) DUMMY(E_FAIL)
HRESULT Console::setDiskEncryptionKeys(const Utf8Str &strCfg) DUMMY(E_FAIL)
void Console::onMouseCapabilityChange(BOOL, BOOL, BOOL, BOOL) TRACE()
void Console::onAdditionsStateChange() TRACE()
void Console::onAdditionsOutdated() DUMMY()
void Console::onMousePointerShapeChange(bool, bool, uint32_t, uint32_t,
uint32_t, uint32_t,
ComSafeArrayIn(uint8_t, aShape)) DUMMY()
void Console::onKeyboardLedsChange(bool, bool, bool) TRACE()
HRESULT Console::onVideoCaptureChange() DUMMY(E_FAIL)
HRESULT Console::onSharedFolderChange(BOOL aGlobal) DUMMY(E_FAIL)

View File

@ -24,6 +24,9 @@
/* VirtualBox includes */
#include "ConsoleImpl.h"
#include <base/printf.h>
#include <os/attached_dataspace.h>
#include <report_session/connection.h>
#include <vbox_pointer/shape_report.h>
class Scan_code
@ -104,12 +107,15 @@ class GenodeConsole : public Console {
private:
Input::Connection _input;
Genode::Signal_receiver _receiver;
Genode::Signal_context _context;
Input::Event *_ev_buf;
unsigned _ax, _ay;
bool _last_received_motion_event_was_absolute;
Input::Connection _input;
Genode::Signal_receiver _receiver;
Genode::Signal_context _context;
Input::Event *_ev_buf;
unsigned _ax, _ay;
bool _last_received_motion_event_was_absolute;
Report::Connection _shape_report_connection;
Genode::Attached_dataspace _shape_report_ds;
Vbox_pointer::Shape_report *_shape_report;
bool _key_status[Input::KEY_MAX + 1];
@ -127,7 +133,10 @@ class GenodeConsole : public Console {
Console(),
_ev_buf(static_cast<Input::Event *>(Genode::env()->rm_session()->attach(_input.dataspace()))),
_ax(0), _ay(0),
_last_received_motion_event_was_absolute(false)
_last_received_motion_event_was_absolute(false),
_shape_report_connection("shape", sizeof(Vbox_pointer::Shape_report)),
_shape_report_ds(_shape_report_connection.dataspace()),
_shape_report(_shape_report_ds.local_addr<Vbox_pointer::Shape_report>())
{
for (unsigned i = 0; i <= Input::KEY_MAX; i++)
_key_status[i] = 0;
@ -284,4 +293,73 @@ class GenodeConsole : public Console {
gMouse->PutEventMultiTouch(mt_number, mt_number, mt_events,
RTTimeMilliTS());
}
void onMouseCapabilityChange(BOOL supportsAbsolute, BOOL supportsRelative,
BOOL supportsMT, BOOL needsHostCursor)
{
if (supportsAbsolute) {
/* let the guest hide the software cursor */
Mouse *gMouse = getMouse();
gMouse->PutMouseEventAbsolute(-1, -1, 0, 0, 0);
}
}
void onMousePointerShapeChange(bool fVisible, bool fAlpha,
uint32_t xHot, uint32_t yHot,
uint32_t width, uint32_t height,
ComSafeArrayIn(BYTE,pShape))
{
com::SafeArray<BYTE> shape_array(ComSafeArrayInArg(pShape));
if (fVisible && ((width == 0) || (height == 0)))
return;
_shape_report->visible = fVisible;
_shape_report->x_hot = xHot;
_shape_report->y_hot = yHot;
_shape_report->width = width;
_shape_report->height = height;
unsigned int and_mask_size = (_shape_report->width + 7) / 8 *
_shape_report->height;
unsigned char *and_mask = shape_array.raw();
unsigned char *shape = and_mask + ((and_mask_size + 3) & ~3);
size_t shape_size = shape_array.size() - (shape - and_mask);
if (shape_size > Vbox_pointer::MAX_SHAPE_SIZE) {
PERR("%s: shape data buffer is too small for %zu bytes",
__func__, shape_size);
return;
}
Genode::memcpy(_shape_report->shape,
shape,
shape_size);
if (fVisible && !fAlpha) {
for (unsigned int i = 0; i < width * height; i++) {
unsigned int *color =
&((unsigned int*)_shape_report->shape)[i];
/* heuristic from VBoxSDL.cpp */
if (and_mask[i / 8] & (1 << (7 - (i % 8)))) {
if (*color & 0x00ffffff)
*color = 0xff000000;
else
*color = 0x00000000;
} else
*color |= 0xff000000;
}
}
_shape_report_connection.submit(sizeof(Vbox_pointer::Shape_report));
}
};

View File

@ -166,7 +166,13 @@ class Genodefb : public Framebuffer
STDMETHODIMP VideoModeSupported(ULONG width, ULONG height, ULONG bpp, BOOL *supported)
{
Assert(!"FixMe");
if (!supported)
return E_POINTER;
*supported = ((width <= (ULONG)_fb_mode.width()) &&
(height <= (ULONG)_fb_mode.height()) &&
(bpp == _fb_mode.bytes_per_pixel() * 8));
return S_OK;
}

View File

@ -1,10 +0,0 @@
+++ src/app/virtualbox/src/VBox/Devices/Graphics/DevVGA.cpp
@@ -5946,7 +5946,7 @@
else
{
#endif /* VBOX_WITH_VMSVGA */
- PCIDevSetVendorId( &pThis->Dev, 0x80ee); /* PCI vendor, just a free bogus value */
+ PCIDevSetVendorId( &pThis->Dev, 0x80ef); /* PCI vendor, just a free bogus value */
PCIDevSetDeviceId( &pThis->Dev, 0xbeef);
#ifdef VBOX_WITH_VMSVGA
}

File diff suppressed because it is too large Load Diff