loader: Adaptation to new nitpicker interface

This commit is contained in:
Norman Feske 2014-06-30 17:47:43 +02:00
parent 8539239fc4
commit 7888e7be02
6 changed files with 693 additions and 746 deletions

View File

@ -21,41 +21,42 @@
namespace Loader {
struct Session_client : Rpc_client<Session>
struct Session_client : Genode::Rpc_client<Session>
{
explicit Session_client(Loader::Session_capability session)
: Rpc_client<Session>(session) { }
Dataspace_capability alloc_rom_module(Name const &name, size_t size) {
Dataspace_capability alloc_rom_module(Name const &name,
size_t size) override {
return call<Rpc_alloc_rom_module>(name, size); }
void commit_rom_module(Name const &name) {
void commit_rom_module(Name const &name) override {
call<Rpc_commit_rom_module>(name); }
void ram_quota(size_t quantum) {
void ram_quota(size_t quantum) override {
call<Rpc_ram_quota>(quantum); }
void constrain_geometry(int width, int height) {
call<Rpc_constrain_geometry>(width, height); }
void constrain_geometry(Area size) override {
call<Rpc_constrain_geometry>(size); }
void parent_view(Nitpicker::View_capability view) {
void parent_view(Nitpicker::View_capability view) override {
call<Rpc_parent_view>(view); }
void view_ready_sigh(Signal_context_capability sigh) {
void view_ready_sigh(Signal_context_capability sigh) override {
call<Rpc_view_ready_sigh>(sigh); }
void fault_sigh(Signal_context_capability sigh) {
void fault_sigh(Signal_context_capability sigh) override {
call<Rpc_fault_sigh>(sigh); }
void start(Name const &binary, Name const &label = "",
Native_pd_args const &pd_args = Native_pd_args()) {
Native_pd_args const &pd_args = Native_pd_args()) override {
call<Rpc_start>(binary, label, pd_args); }
Nitpicker::View_capability view() {
return call<Rpc_view>(); }
void view_geometry(Rect rect, Point offset) override {
call<Rpc_view_geometry>(rect, offset); }
View_geometry view_geometry() {
return call<Rpc_view_geometry>(); }
Area view_size() const override {
return call<Rpc_view_size>(); }
};
}

View File

@ -21,10 +21,18 @@
#include <nitpicker_session/client.h>
#include <base/signal.h>
#include <session/session.h>
#include <util/geometry.h>
namespace Loader {
using namespace Genode;
typedef Genode::Point<> Point;
typedef Genode::Area<> Area;
typedef Genode::Rect<> Rect;
using Genode::Dataspace_capability;
using Genode::Signal_context_capability;
using Genode::Native_pd_args;
using Genode::Meta::Type_tuple;
struct Session : Genode::Session
{
@ -41,18 +49,6 @@ namespace Loader {
struct View_does_not_exist : Exception { };
struct Rom_module_does_not_exist : Exception { };
/**
* Return argument of 'view_geometry()'
*/
struct View_geometry
{
int width, height;
int buf_x, buf_y;
View_geometry(): width(0), height(0), buf_x(0), buf_y() {}
View_geometry(int w, int h, int x, int y): width(w), height(h), buf_x(x), buf_y(y) {}
};
typedef Genode::Rpc_in_buffer<64> Name;
typedef Genode::Rpc_in_buffer<128> Path;
@ -109,7 +105,7 @@ namespace Loader {
* Calling this function prior 'start()' enables the virtualization
* of the nitpicker session interface.
*/
virtual void constrain_geometry(int width, int height) = 0;
virtual void constrain_geometry(Area size) = 0;
/**
* Set the parent view of the subsystem's view.
@ -148,18 +144,14 @@ namespace Loader {
Native_pd_args const &pd_args = Native_pd_args()) = 0;
/**
* Return first nitpicker view created by the loaded subsystem
*
* \throw View_does_not_exist
* Set view geometry and buffer offset
*/
virtual Nitpicker::View_capability view() = 0;
virtual void view_geometry(Rect rect, Point offset) = 0;
/**
* Return view geometry as initialized by the loaded subsystem
*
* \throw View_does_not_exist
* Return view size as initialized by the loaded subsystem
*/
virtual View_geometry view_geometry() = 0;
virtual Area view_size() const = 0;
/*******************
@ -172,16 +164,18 @@ namespace Loader {
GENODE_TYPE_LIST(Rom_module_does_not_exist),
Name const &);
GENODE_RPC(Rpc_ram_quota, void, ram_quota, size_t);
GENODE_RPC(Rpc_constrain_geometry, void, constrain_geometry, int, int);
GENODE_RPC(Rpc_constrain_geometry, void, constrain_geometry, Area);
GENODE_RPC(Rpc_parent_view, void, parent_view, Nitpicker::View_capability);
GENODE_RPC(Rpc_view_ready_sigh, void, view_ready_sigh, Signal_context_capability);
GENODE_RPC(Rpc_fault_sigh, void, fault_sigh, Signal_context_capability);
GENODE_RPC_THROW(Rpc_start, void, start,
GENODE_TYPE_LIST(Rom_module_does_not_exist),
Name const &, Name const &, Native_pd_args const &);
GENODE_RPC_THROW(Rpc_view, Nitpicker::View_capability, view,
GENODE_RPC_THROW(Rpc_view_geometry, void, view_geometry,
GENODE_TYPE_LIST(View_does_not_exist),
Rect, Point);
GENODE_RPC_THROW(Rpc_view_size, Area, view_size,
GENODE_TYPE_LIST(View_does_not_exist));
GENODE_RPC(Rpc_view_geometry, View_geometry, view_geometry);
/*
* 'GENODE_RPC_INTERFACE' declaration done manually
@ -191,17 +185,17 @@ namespace Loader {
* construct the type list by hand using nested type tuples instead
* of employing the convenience macro 'GENODE_RPC_INTERFACE'.
*/
typedef Meta::Type_tuple<Rpc_alloc_rom_module,
Meta::Type_tuple<Rpc_commit_rom_module,
Meta::Type_tuple<Rpc_ram_quota,
Meta::Type_tuple<Rpc_constrain_geometry,
Meta::Type_tuple<Rpc_parent_view,
Meta::Type_tuple<Rpc_view_ready_sigh,
Meta::Type_tuple<Rpc_fault_sigh,
Meta::Type_tuple<Rpc_start,
Meta::Type_tuple<Rpc_view,
Meta::Type_tuple<Rpc_view_geometry,
Meta::Empty>
typedef Type_tuple<Rpc_alloc_rom_module,
Type_tuple<Rpc_commit_rom_module,
Type_tuple<Rpc_ram_quota,
Type_tuple<Rpc_constrain_geometry,
Type_tuple<Rpc_parent_view,
Type_tuple<Rpc_view_ready_sigh,
Type_tuple<Rpc_fault_sigh,
Type_tuple<Rpc_start,
Type_tuple<Rpc_view_geometry,
Type_tuple<Rpc_view_size,
Genode::Meta::Empty>
> > > > > > > > > Rpc_functions;
};
}

View File

@ -29,80 +29,78 @@ namespace Input {
using namespace Genode;
struct Transformer
{
struct Delta { int const x, y; };
typedef Genode::Point<> Motion_delta;
virtual Delta delta() = 0;
};
class Session_component : public Rpc_object<Session>
{
private:
Session_client _real_input;
Transformer &_transformer;
Event * const _ev_buf;
public:
/**
* Constructor
*/
Session_component(Session_capability real_input,
Transformer &transformer)
:
_real_input(real_input), _transformer(transformer),
_ev_buf(env()->rm_session()->attach(_real_input.dataspace()))
{ }
/**
* Destructor
*/
~Session_component() { env()->rm_session()->detach(_ev_buf); }
/*****************************
** Input session interface **
*****************************/
Dataspace_capability dataspace() override { return _real_input.dataspace(); }
bool is_pending() const override { return _real_input.is_pending(); }
int flush() override
{
/* translate mouse position to child's coordinate system */
Transformer::Delta delta = _transformer.delta();
int const num_ev = _real_input.flush();
for (int i = 0; i < num_ev; i++) {
Input::Event &ev = _ev_buf[i];
if ((ev.type() == Input::Event::MOTION)
|| (ev.type() == Input::Event::WHEEL)
|| (ev.code() == Input::BTN_LEFT)
|| (ev.code() == Input::BTN_RIGHT)
|| (ev.code() == Input::BTN_MIDDLE)) {
ev = Input::Event(ev.type(),
ev.code(),
ev.ax() - delta.x,
ev.ay() - delta.y,
ev.rx(),
ev.ry());
}
}
return num_ev;
}
void sigh(Signal_context_capability sigh) override
{
_real_input.sigh(sigh);
}
};
class Session_component;
}
class Input::Session_component : public Rpc_object<Session>
{
private:
Session_client _real_input;
Motion_delta &_motion_delta;
Event * const _ev_buf;
public:
/**
* Constructor
*/
Session_component(Session_capability real_input,
Motion_delta &motion_delta)
:
_real_input(real_input), _motion_delta(motion_delta),
_ev_buf(env()->rm_session()->attach(_real_input.dataspace()))
{ }
/**
* Destructor
*/
~Session_component() { env()->rm_session()->detach(_ev_buf); }
/*****************************
** Input session interface **
*****************************/
Dataspace_capability dataspace() override { return _real_input.dataspace(); }
bool is_pending() const override { return _real_input.is_pending(); }
int flush() override
{
/* translate mouse position to child's coordinate system */
Motion_delta const delta = _motion_delta;
int const num_ev = _real_input.flush();
for (int i = 0; i < num_ev; i++) {
Input::Event &ev = _ev_buf[i];
if ((ev.type() == Input::Event::MOTION)
|| (ev.type() == Input::Event::WHEEL)
|| (ev.code() == Input::BTN_LEFT)
|| (ev.code() == Input::BTN_RIGHT)
|| (ev.code() == Input::BTN_MIDDLE)) {
ev = Input::Event(ev.type(),
ev.code(),
ev.ax() + delta.x(),
ev.ay() + delta.y(),
ev.rx(),
ev.ry());
}
}
return num_ev;
}
void sigh(Signal_context_capability sigh) override
{
_real_input.sigh(sigh);
}
};
#endif /* _INPUT_H_ */

View File

@ -19,7 +19,6 @@
#include <base/sleep.h>
#include <loader_session/loader_session.h>
#include <cap_session/connection.h>
#include <nitpicker_view/capability.h>
#include <root/component.h>
/* local includes */
@ -33,395 +32,397 @@ namespace Loader {
using namespace Genode;
class Session_component;
class Root;
}
class Session_component : public Rpc_object<Session>
{
private:
struct Local_rom_service : Service
class Loader::Session_component : public Rpc_object<Session>
{
private:
struct Local_rom_service : Service
{
Rpc_entrypoint &_ep;
Allocator &_md_alloc;
Parent_service _parent_rom_service;
Rom_module_registry &_rom_modules;
Lock _lock;
List<Rom_session_component> _rom_sessions;
void _close(Rom_session_component *rom)
{
Rpc_entrypoint &_ep;
Allocator &_md_alloc;
Parent_service _parent_rom_service;
Rom_module_registry &_rom_modules;
Lock _lock;
List<Rom_session_component> _rom_sessions;
void _close(Rom_session_component *rom)
{
_ep.dissolve(rom);
_rom_sessions.remove(rom);
destroy(&_md_alloc, rom);
}
Local_rom_service(Rpc_entrypoint &ep,
Allocator &md_alloc,
Rom_module_registry &rom_modules)
:
Service("virtual_rom"),
_ep(ep),
_md_alloc(md_alloc),
_parent_rom_service(Rom_session::service_name()),
_rom_modules(rom_modules)
{ }
~Local_rom_service()
{
Lock::Guard guard(_lock);
while (_rom_sessions.first()) {
_close(_rom_sessions.first()); }
}
Genode::Session_capability session(char const *args,
Affinity const &affinity)
{
/* try to find ROM module at local ROM service */
try {
Lock::Guard guard(_lock);
char name[Session::Name::MAX_SIZE];
/* extract filename from session arguments */
Arg_string::find_arg(args, "filename")
.string(name, sizeof(name), "");
Rom_module &module = _rom_modules.lookup_and_lock(name);
Rom_session_component *rom = new (&_md_alloc)
Rom_session_component(module);
_rom_sessions.insert(rom);
return _ep.manage(rom);
} catch (...) { }
/* fall back to parent_rom_service */
return _parent_rom_service.session(args, affinity);
}
void close(Session_capability session)
{
Lock::Guard guard(_lock);
Rpc_object_base *rom = _ep.lookup_and_lock(session);
Rom_session_component *component =
dynamic_cast<Rom_session_component *>(rom);
if (component) {
_close(component);
return;
}
_parent_rom_service.close(session);
}
void upgrade(Session_capability session, const char *) { }
};
/**
* Common base class of 'Local_cpu_service' and 'Local_rm_service'
*/
struct Intercepted_parent_service : Service
{
Signal_context_capability fault_sigh;
Intercepted_parent_service(char const *name) : Service(name) { }
void close(Session_capability session)
{
env()->parent()->close(session);
}
void upgrade(Session_capability session, const char *) { }
};
/**
* Intercept CPU session requests to install default exception
* handler
*/
struct Local_cpu_service : Intercepted_parent_service
{
Local_cpu_service() : Intercepted_parent_service("CPU") { }
Genode::Session_capability session(char const *args,
Affinity const &affinity)
{
Capability<Cpu_session> cap = env()->parent()->session<Cpu_session>(args, affinity);
Cpu_session_client(cap).exception_handler(Thread_capability(), fault_sigh);
return cap;
}
};
/**
* Intercept RM session requests to install default fault handler
*/
struct Local_rm_service : Intercepted_parent_service
{
Local_rm_service() : Intercepted_parent_service("RM") { }
Genode::Session_capability session(char const *args,
Affinity const &affinity)
{
Capability<Rm_session> cap = env()->parent()->session<Rm_session>(args, affinity);
Rm_session_client(cap).fault_handler(fault_sigh);
return cap;
}
};
struct Local_nitpicker_service : Service
{
Rpc_entrypoint &ep;
Allocator &_md_alloc;
int _max_width;
int _max_height;
Nitpicker::View_capability _parent_view;
Signal_context_capability view_ready_sigh;
Nitpicker::Session_component *open_session;
Local_nitpicker_service(Rpc_entrypoint &ep,
Allocator &md_alloc)
:
Service("virtual_nitpicker"),
ep(ep),
_md_alloc(md_alloc),
_max_width(-1),
_max_height(-1),
open_session(0)
{ }
~Local_nitpicker_service()
{
if (!open_session)
return;
ep.dissolve(open_session);
destroy(&_md_alloc, open_session);
}
void constrain_geometry(int width, int height)
{
_max_width = width, _max_height = height;
}
void parent_view(Nitpicker::View_capability view)
{
_parent_view = view;
}
Genode::Session_capability session(char const *args,
Affinity const &)
{
if (open_session)
throw Unavailable();
open_session = new (&_md_alloc)
Nitpicker::Session_component(ep,
_max_width,
_max_height,
_parent_view,
view_ready_sigh,
args);
return ep.manage(open_session);
}
void upgrade(Genode::Session_capability session, const char *) { }
};
enum { STACK_SIZE = 2*4096 };
size_t _ram_quota;
Ram_session_client_guard _ram_session_client;
Heap _md_alloc;
size_t _subsystem_ram_quota_limit;
Rpc_entrypoint _ep;
Service_registry _parent_services;
Rom_module_registry _rom_modules;
Local_rom_service _rom_service;
Local_cpu_service _cpu_service;
Local_rm_service _rm_service;
Local_nitpicker_service _nitpicker_service;
Signal_context_capability _fault_sigh;
Child *_child;
/**
* Return virtual nitpicker session component
*/
Nitpicker::Session_component *_virtual_nitpicker_session()
{
if (!_nitpicker_service.open_session)
throw View_does_not_exist();
return _nitpicker_service.open_session;
_ep.dissolve(rom);
_rom_sessions.remove(rom);
destroy(&_md_alloc, rom);
}
public:
/**
* Constructor
*/
Session_component(size_t quota, Ram_session &ram, Cap_session &cap)
Local_rom_service(Rpc_entrypoint &ep,
Allocator &md_alloc,
Rom_module_registry &rom_modules)
:
_ram_quota(quota),
_ram_session_client(env()->ram_session_cap(), _ram_quota),
_md_alloc(&_ram_session_client, env()->rm_session()),
_subsystem_ram_quota_limit(0),
_ep(&cap, STACK_SIZE, "session_ep"),
_rom_modules(_ram_session_client, _md_alloc),
_rom_service(_ep, _md_alloc, _rom_modules),
_nitpicker_service(_ep, _md_alloc),
_child(0)
Service("virtual_rom"),
_ep(ep),
_md_alloc(md_alloc),
_parent_rom_service(Rom_session::service_name()),
_rom_modules(rom_modules)
{ }
~Session_component()
~Local_rom_service()
{
if (_child)
destroy(&_md_alloc, _child);
Lock::Guard guard(_lock);
/*
* The parent-service registry is populated by the 'Child'
* on demand. Revert those allocations.
*/
while (Service *service = _parent_services.find_by_server(0)) {
_parent_services.remove(service);
destroy(env()->heap(), service);
}
while (_rom_sessions.first()) {
_close(_rom_sessions.first()); }
}
/******************************
** Loader session interface **
******************************/
Dataspace_capability alloc_rom_module(Name const &name, size_t size)
{
return _rom_modules.alloc_rom_module(name.string(), size);
}
void commit_rom_module(Name const &name)
Genode::Session_capability session(char const *args,
Affinity const &affinity)
{
/* try to find ROM module at local ROM service */
try {
_rom_modules.commit_rom_module(name.string()); }
catch (Rom_module_registry::Lookup_failed) {
throw Rom_module_does_not_exist(); }
Lock::Guard guard(_lock);
char name[Session::Name::MAX_SIZE];
/* extract filename from session arguments */
Arg_string::find_arg(args, "filename")
.string(name, sizeof(name), "");
Rom_module &module = _rom_modules.lookup_and_lock(name);
Rom_session_component *rom = new (&_md_alloc)
Rom_session_component(module);
_rom_sessions.insert(rom);
return _ep.manage(rom);
} catch (...) { }
/* fall back to parent_rom_service */
return _parent_rom_service.session(args, affinity);
}
void ram_quota(size_t quantum)
void close(Session_capability session)
{
_subsystem_ram_quota_limit = quantum;
Lock::Guard guard(_lock);
Rpc_object_base *rom = _ep.lookup_and_lock(session);
Rom_session_component *component =
dynamic_cast<Rom_session_component *>(rom);
if (component) {
_close(component);
return;
}
_parent_rom_service.close(session);
}
void constrain_geometry(int width, int height)
void upgrade(Session_capability session, const char *) { }
};
/**
* Common base class of 'Local_cpu_service' and 'Local_rm_service'
*/
struct Intercepted_parent_service : Service
{
Signal_context_capability fault_sigh;
Intercepted_parent_service(char const *name) : Service(name) { }
void close(Session_capability session)
{
_nitpicker_service.constrain_geometry(width, height);
env()->parent()->close(session);
}
void upgrade(Session_capability session, const char *) { }
};
/**
* Intercept CPU session requests to install default exception
* handler
*/
struct Local_cpu_service : Intercepted_parent_service
{
Local_cpu_service() : Intercepted_parent_service("CPU") { }
Genode::Session_capability session(char const *args,
Affinity const &affinity)
{
Capability<Cpu_session> cap = env()->parent()->session<Cpu_session>(args, affinity);
Cpu_session_client(cap).exception_handler(Thread_capability(), fault_sigh);
return cap;
}
};
/**
* Intercept RM session requests to install default fault handler
*/
struct Local_rm_service : Intercepted_parent_service
{
Local_rm_service() : Intercepted_parent_service("RM") { }
Genode::Session_capability session(char const *args,
Affinity const &affinity)
{
Capability<Rm_session> cap = env()->parent()->session<Rm_session>(args, affinity);
Rm_session_client(cap).fault_handler(fault_sigh);
return cap;
}
};
struct Local_nitpicker_service : Service
{
Rpc_entrypoint &_ep;
Ram_session &_ram;
Allocator &_md_alloc;
Area _max_size;
Nitpicker::View_capability _parent_view;
Signal_context_capability view_ready_sigh;
Nitpicker::Session_component *open_session;
Local_nitpicker_service(Rpc_entrypoint &ep, Ram_session &ram,
Allocator &md_alloc)
:
Service("virtual_nitpicker"),
_ep(ep),
_ram(ram),
_md_alloc(md_alloc),
open_session(0)
{ }
~Local_nitpicker_service()
{
if (!open_session)
return;
_ep.dissolve(open_session);
destroy(&_md_alloc, open_session);
}
void constrain_geometry(Area size)
{
_max_size = size;
}
void parent_view(Nitpicker::View_capability view)
{
_nitpicker_service.parent_view(view);
_parent_view = view;
}
void view_ready_sigh(Signal_context_capability sigh)
Genode::Session_capability session(char const *args,
Affinity const &)
{
_nitpicker_service.view_ready_sigh = sigh;
if (open_session)
throw Unavailable();
open_session = new (&_md_alloc)
Nitpicker::Session_component(_ep,
_ram,
_max_size,
_parent_view,
view_ready_sigh,
args);
return _ep.manage(open_session);
}
void fault_sigh(Signal_context_capability sigh)
{
/*
* CPU exception handler for CPU sessions originating from the
* subsystem.
*/
_cpu_service.fault_sigh = sigh;
void upgrade(Genode::Session_capability session, const char *) { }
};
/*
* RM fault handler for RM sessions originating from the
* subsystem.
*/
_rm_service.fault_sigh = sigh;
enum { STACK_SIZE = 2*4096 };
/*
* CPU exception and RM fault handler for the immediate child.
*/
_fault_sigh = sigh;
}
size_t _ram_quota;
Ram_session_client_guard _ram_session_client;
Heap _md_alloc;
size_t _subsystem_ram_quota_limit;
Rpc_entrypoint _ep;
Service_registry _parent_services;
Rom_module_registry _rom_modules;
Local_rom_service _rom_service;
Local_cpu_service _cpu_service;
Local_rm_service _rm_service;
Local_nitpicker_service _nitpicker_service;
Signal_context_capability _fault_sigh;
Child *_child;
void start(Name const &binary_name, Name const &label,
Genode::Native_pd_args const &pd_args)
{
if (_child) {
PWRN("cannot start subsystem twice");
return;
}
/**
* Return virtual nitpicker session component
*/
Nitpicker::Session_component &_virtual_nitpicker_session() const
{
if (!_nitpicker_service.open_session)
throw View_does_not_exist();
size_t const ram_quota = (_subsystem_ram_quota_limit > 0) ?
min(_subsystem_ram_quota_limit, _ram_session_client.avail()) :
_ram_session_client.avail();
return *_nitpicker_service.open_session;
}
try {
_child = new (&_md_alloc)
Child(binary_name.string(), label.string(),
pd_args, _ep, _ram_session_client,
ram_quota, _parent_services, _rom_service,
_cpu_service, _rm_service, _nitpicker_service,
_fault_sigh);
}
catch (Genode::Parent::Service_denied) {
throw Rom_module_does_not_exist(); }
}
public:
Nitpicker::View_capability view()
{
return _virtual_nitpicker_session()->loader_view();
}
/**
* Constructor
*/
Session_component(size_t quota, Ram_session &ram, Cap_session &cap)
:
_ram_quota(quota),
_ram_session_client(env()->ram_session_cap(), _ram_quota),
_md_alloc(&_ram_session_client, env()->rm_session()),
_subsystem_ram_quota_limit(0),
_ep(&cap, STACK_SIZE, "session_ep"),
_rom_modules(_ram_session_client, _md_alloc),
_rom_service(_ep, _md_alloc, _rom_modules),
_nitpicker_service(_ep, _ram_session_client, _md_alloc),
_child(0)
{ }
View_geometry view_geometry()
{
return _virtual_nitpicker_session()->loader_view_geometry();
}
};
~Session_component()
{
if (_child)
destroy(&_md_alloc, _child);
class Root : public Root_component<Session_component>
{
private:
Ram_session &_ram;
Cap_session &_cap;
protected:
Session_component *_create_session(const char *args)
{
size_t quota =
Arg_string::find_arg(args, "ram_quota").long_value(0);
return new (md_alloc()) Session_component(quota, _ram, _cap);
}
public:
/**
* Constructor
*
* \param session_ep entry point for managing ram session objects
* \param md_alloc meta-data allocator to be used by root
* component
/*
* The parent-service registry is populated by the 'Child'
* on demand. Revert those allocations.
*/
Root(Rpc_entrypoint &session_ep, Allocator &md_alloc,
Ram_session &ram, Cap_session &cap)
:
Root_component<Session_component>(&session_ep, &md_alloc),
_ram(ram), _cap(cap)
{ }
};
}
while (Service *service = _parent_services.find_by_server(0)) {
_parent_services.remove(service);
destroy(env()->heap(), service);
}
}
/******************************
** Loader session interface **
******************************/
Dataspace_capability alloc_rom_module(Name const &name, size_t size) override
{
return _rom_modules.alloc_rom_module(name.string(), size);
}
void commit_rom_module(Name const &name) override
{
try {
_rom_modules.commit_rom_module(name.string()); }
catch (Rom_module_registry::Lookup_failed) {
throw Rom_module_does_not_exist(); }
}
void ram_quota(size_t quantum) override
{
_subsystem_ram_quota_limit = quantum;
}
void constrain_geometry(Area size) override
{
_nitpicker_service.constrain_geometry(size);
}
void parent_view(Nitpicker::View_capability view) override
{
_nitpicker_service.parent_view(view);
}
void view_ready_sigh(Signal_context_capability sigh) override
{
_nitpicker_service.view_ready_sigh = sigh;
}
void fault_sigh(Signal_context_capability sigh) override
{
/*
* CPU exception handler for CPU sessions originating from the
* subsystem.
*/
_cpu_service.fault_sigh = sigh;
/*
* RM fault handler for RM sessions originating from the
* subsystem.
*/
_rm_service.fault_sigh = sigh;
/*
* CPU exception and RM fault handler for the immediate child.
*/
_fault_sigh = sigh;
}
void start(Name const &binary_name, Name const &label,
Genode::Native_pd_args const &pd_args) override
{
if (_child) {
PWRN("cannot start subsystem twice");
return;
}
size_t const ram_quota = (_subsystem_ram_quota_limit > 0) ?
min(_subsystem_ram_quota_limit, _ram_session_client.avail()) :
_ram_session_client.avail();
try {
_child = new (&_md_alloc)
Child(binary_name.string(), label.string(),
pd_args, _ep, _ram_session_client,
ram_quota, _parent_services, _rom_service,
_cpu_service, _rm_service, _nitpicker_service,
_fault_sigh);
}
catch (Genode::Parent::Service_denied) {
throw Rom_module_does_not_exist(); }
}
void view_geometry(Rect rect, Point offset) override
{
_virtual_nitpicker_session().loader_view_geometry(rect, offset);
}
Area view_size() const override
{
return _virtual_nitpicker_session().loader_view_size();
}
};
class Loader::Root : public Root_component<Session_component>
{
private:
Ram_session &_ram;
Cap_session &_cap;
protected:
Session_component *_create_session(const char *args)
{
size_t quota =
Arg_string::find_arg(args, "ram_quota").long_value(0);
return new (md_alloc()) Session_component(quota, _ram, _cap);
}
public:
/**
* Constructor
*
* \param session_ep entry point for managing ram session objects
* \param md_alloc meta-data allocator to be used by root
* component
*/
Root(Rpc_entrypoint &session_ep, Allocator &md_alloc,
Ram_session &ram, Cap_session &cap)
:
Root_component<Session_component>(&session_ep, &md_alloc),
_ram(ram), _cap(cap)
{ }
};
int main()

View File

@ -19,295 +19,259 @@
#include <util/arg_string.h>
#include <util/misc_math.h>
#include <base/signal.h>
#include <os/attached_ram_dataspace.h>
#include <nitpicker_session/connection.h>
#include <nitpicker_session/nitpicker_session.h>
#include <nitpicker_view/client.h>
/* local includes */
#include <input.h>
namespace Nitpicker {
using namespace Genode;
/**
* View interface provided to the loader client
*/
class Loader_view_component : public Rpc_object<View>
{
private:
View_client _view; /* wrapped view */
int _x, _y, _buf_x, _buf_y;
public:
/**
* Constructor
*/
Loader_view_component(View_capability view_cap)
:
_view(view_cap), _x(0), _y(0), _buf_x(0), _buf_y(0)
{ }
int x() const { return _x; }
int y() const { return _y; }
int buf_x() const { return _buf_x; }
int buf_y() const { return _buf_y; }
namespace Nitpicker { class Session_component; }
/******************************
** Nitpicker view interface **
******************************/
class Nitpicker::Session_component : public Genode::Rpc_object<Session>
{
private:
int viewport(int x, int y, int w, int h,
int buf_x, int buf_y, bool redraw)
{
_x = x, _y = y, _buf_x = buf_x, _buf_y = buf_y;
/**
* Signal handler to be notified once the geometry of the view is
* known.
*/
Genode::Signal_context_capability _view_ready_sigh;
return _view.viewport(x, y, w, h, buf_x, buf_y, redraw);
Genode::Rpc_entrypoint &_ep;
Area _max_size;
Nitpicker::Connection _nitpicker;
View_handle _parent_view_handle;
/*
* Physical view
*/
View_handle _view_handle;
Rect _view_geometry;
Point _view_offset;
/*
* Geometry of virtual view presented to the loaded subsystem
*/
Rect _virt_view_geometry;
Point _virt_view_offset;
bool _virt_view_geometry_defined = false;
Input::Motion_delta _motion_delta;
Input::Session_component _proxy_input;
Input::Session_capability _proxy_input_cap;
static long _session_arg(const char *arg, const char *key) {
return Genode::Arg_string::find_arg(arg, key).long_value(0); }
/*
* Command buffer
*/
typedef Nitpicker::Session::Command_buffer Command_buffer;
Genode::Attached_ram_dataspace _command_ds;
Command_buffer &_command_buffer = *_command_ds.local_addr<Command_buffer>();
void _propagate_view_offset()
{
_nitpicker.enqueue<Command::Offset>(_view_handle,
_view_offset + _virt_view_offset);
}
void _update_motion_delta()
{
_motion_delta = _virt_view_geometry.p1() - _view_geometry.p1();
}
void _execute_command(Command const &command)
{
switch (command.opcode) {
case Command::OP_GEOMETRY:
{
_virt_view_geometry = command.geometry.rect;
if (!_virt_view_geometry_defined)
Genode::Signal_transmitter(_view_ready_sigh).submit();
_virt_view_geometry_defined = true;
_update_motion_delta();
return;
}
case Command::OP_OFFSET:
{
_virt_view_offset = command.offset.offset;
_propagate_view_offset();
_nitpicker.execute();
return;
}
case Command::OP_TO_FRONT:
{
_nitpicker.enqueue<Command::To_front>(_view_handle, _parent_view_handle);
_nitpicker.execute();
return;
}
case Command::OP_TO_BACK:
{
PDBG("OP_TO_BACK not implemented");
return;
}
case Command::OP_BACKGROUND:
{
PDBG("OP_BACKGROUND not implemented");
return;
}
case Command::OP_TITLE:
{
_nitpicker.enqueue(command);
_nitpicker.execute();
return;
}
case Command::OP_NOP:
return;
}
}
int stack(View_capability neighbor_cap, bool behind, bool redraw)
{
return _view.stack(neighbor_cap, behind, redraw);
}
public:
int title(Title const &title)
{
return _view.title(title.string());
}
};
/**
* Constructor
*/
Session_component(Genode::Rpc_entrypoint &ep,
Genode::Ram_session &ram,
Area max_size,
Nitpicker::View_capability parent_view,
Genode::Signal_context_capability view_ready_sigh,
const char *args)
:
_view_ready_sigh(view_ready_sigh),
_ep(ep),
_max_size(max_size),
/* import parent view */
_parent_view_handle(_nitpicker.view_handle(parent_view)),
/* create nitpicker view */
_view_handle(_nitpicker.create_view(_parent_view_handle)),
_proxy_input(_nitpicker.input_session(), _motion_delta),
_proxy_input_cap(_ep.manage(&_proxy_input)),
_command_ds(&ram, sizeof(Command_buffer))
{ }
/**
* View interface exposed to the subsystem
*/
class View_component : public Rpc_object<View>
{
private:
/*********************************
** Nitpicker session interface **
*********************************/
View_client _view; /* wrapped view */
Signal_context_capability _sigh;
bool _viewport_initialized;
int _x, _y, _w, _h, _buf_x, _buf_y;
Framebuffer::Session_capability framebuffer_session() override
{
return _nitpicker.framebuffer_session();
}
public:
Input::Session_capability input_session() override
{
return _proxy_input_cap;
}
/**
* Constructor
*/
View_component(View_capability view_cap,
Signal_context_capability sigh)
:
_view(view_cap), _sigh(sigh), _viewport_initialized(false),
_x(0), _y(0), _w(0), _h(0), _buf_x(0), _buf_y(0)
{ }
View_handle create_view(View_handle) override
{
return View_handle(1);
}
int x() const { return _x; }
int y() const { return _y; }
int w() const { return _w; }
int h() const { return _h; }
int buf_x() const { return _buf_x; }
int buf_y() const { return _buf_y; }
void destroy_view(View_handle view) override { }
View_handle view_handle(View_capability, View_handle) override
{
return View_handle();
}
/******************************
** Nitpicker view interface **
******************************/
View_capability view_capability(View_handle) override
{
return View_capability();
}
int viewport(int x, int y, int w, int h,
int buf_x, int buf_y, bool redraw)
{
_x = x; _y = y; _w = w; _h = h;
_buf_x = buf_x; _buf_y = buf_y;
void release_view_handle(View_handle) override { }
if (_viewport_initialized)
return 0;
Genode::Dataspace_capability command_dataspace() override
{
return _command_ds.cap();
}
_viewport_initialized = true;
void execute() override
{
for (unsigned i = 0; i < _command_buffer.num(); i++)
_execute_command(_command_buffer.get(i));
}
/* hide the view and let the application set the viewport */
int result = _view.viewport(0, 0, 0, 0, 0, 0, true);
Framebuffer::Mode mode() override
{
int mode_width = _max_size.valid() ?
_max_size.w() :
_nitpicker.mode().width();
/* signal readyness of the view */
if (_sigh.valid())
Signal_transmitter(_sigh).submit();
int mode_height = _max_size.valid() ?
_max_size.h() :
_nitpicker.mode().height();
return result;
}
return Framebuffer::Mode(mode_width, mode_height,
_nitpicker.mode().format());
}
int stack(View_capability neighbor_cap, bool behind, bool redraw)
{
/*
* Only one child view is supported, so the stack request can
* be ignored.
*/
return 0;
}
void mode_sigh(Genode::Signal_context_capability) override { }
int title(Title const &title)
{
return _view.title(title.string());
}
};
void buffer(Framebuffer::Mode mode, bool use_alpha) override
{
_nitpicker.buffer(mode, use_alpha);
}
void focus(Genode::Capability<Session>) override { }
class Session_component : public Rpc_object<Session>,
public Input::Transformer
{
private:
/**
* Return geometry of loader view
*/
Area loader_view_size() const
{
int const width = _max_size.valid()
? Genode::min(_virt_view_geometry.w(), _max_size.w())
: _virt_view_geometry.w();
Rpc_entrypoint &_ep;
int const height = _max_size.valid()
? Genode::min(_virt_view_geometry.h(), _max_size.h())
: _virt_view_geometry.h();
int _max_width;
int _max_height;
return Area(width, height);
}
Nitpicker::Connection _nitpicker;
View_capability _nitpicker_view;
/**
* Define geometry of loader view
*/
void loader_view_geometry(Rect rect, Point offset)
{
typedef Nitpicker::Session::Command Command;
View_component _proxy_view;
View_capability _proxy_view_cap;
_view_geometry = rect;
_view_offset = offset;
Loader_view_component _loader_view;
View_capability _loader_view_cap;
_propagate_view_offset();
_nitpicker.enqueue<Command::Geometry>(_view_handle, _view_geometry);
_nitpicker.enqueue<Command::To_front>(_view_handle, _parent_view_handle);
_nitpicker.execute();
Input::Session_component _proxy_input;
Input::Session_capability _proxy_input_cap;
static long _session_arg(const char *arg, const char *key) {
return Arg_string::find_arg(arg, key).long_value(0); }
public:
/**
* Constructor
*/
Session_component(Rpc_entrypoint &ep,
int max_width,
int max_height,
Nitpicker::View_capability parent_view,
Signal_context_capability view_ready_sigh,
const char *args)
:
_ep(ep),
_max_width(max_width),
_max_height(max_height),
/* create Nitpicker view */
_nitpicker_view(_nitpicker.create_view(parent_view)),
/* create proxy view component for the child */
_proxy_view(_nitpicker_view, view_ready_sigh),
_proxy_view_cap(_ep.manage(&_proxy_view)),
/* create view component accessed by the loader client */
_loader_view(_nitpicker_view),
_loader_view_cap(_ep.manage(&_loader_view)),
_proxy_input(_nitpicker.input_session(), *this),
_proxy_input_cap(_ep.manage(&_proxy_input))
{ }
/*********************************
** Nitpicker session interface **
*********************************/
Framebuffer::Session_capability framebuffer_session() override
{
return _nitpicker.framebuffer_session();
}
Input::Session_capability input_session() override
{
return _proxy_input_cap;
}
View_capability create_view(View_capability) override
{
return _proxy_view_cap;
}
void destroy_view(View_capability view) override
{
_nitpicker.destroy_view(_nitpicker_view);
}
int background(View_capability view) override
{
/* not forwarding to real nitpicker session */
return 0;
}
Framebuffer::Mode mode() override
{
int mode_width = (_max_width > -1) ?
_max_width :
_nitpicker.mode().width();
int mode_height = (_max_height > -1) ?
_max_height :
_nitpicker.mode().height();
return Framebuffer::Mode(mode_width, mode_height,
_nitpicker.mode().format());
}
void buffer(Framebuffer::Mode mode, bool use_alpha) override
{
_nitpicker.buffer(mode, use_alpha);
}
void focus(Capability<Session>) override { }
/**********************************
** Input::Transformer interface **
**********************************/
Input::Transformer::Delta delta()
{
/* translate mouse position to child's coordinate system */
Input::Transformer::Delta result = {
_loader_view.x() + _loader_view.buf_x() +
_proxy_view.x() + _proxy_view.buf_x(),
_loader_view.y() + _loader_view.buf_y() +
_proxy_view.y() + _proxy_view.buf_y() };
return result;
}
/**
* Return the client-specific wrapper view for the Nitpicker view
* showing the child content
*/
View_capability loader_view() { return _loader_view_cap; }
/**
* Return geometry of loader view
*/
Loader::Session::View_geometry loader_view_geometry()
{
int view_width = (_max_width > -1) ?
min(_proxy_view.w(), _max_width) :
_proxy_view.w();
int view_height = (_max_height > -1) ?
min(_proxy_view.h(), _max_height) :
_proxy_view.h();
Loader::Session::View_geometry result(
view_width,
view_height,
_proxy_view.buf_x(),
_proxy_view.buf_y());
return result;
}
};
}
_update_motion_delta();
}
};
#endif /* _NITPICKER_H_ */

View File

@ -14,18 +14,16 @@
#include <base/printf.h>
#include <base/sleep.h>
#include <loader_session/connection.h>
#include <nitpicker_session/client.h>
#include <timer_session/connection.h>
using namespace Genode;
int main(int argc, char **argv)
{
Loader::Connection loader(8*1024*1024);
static Signal_receiver sig_rec;
static Genode::Signal_receiver sig_rec;
Signal_context sig_ctx;
Genode::Signal_context sig_ctx;
loader.view_ready_sigh(sig_rec.manage(&sig_ctx));
@ -33,31 +31,22 @@ int main(int argc, char **argv)
sig_rec.wait_for_signal();
Loader::Session::View_geometry geometry = loader.view_geometry();
Nitpicker::View_capability view_cap = loader.view();
static Nitpicker_connection nitpicker;
Nitpicker::Session::View_handle view_handle = nitpicker.view_handle(view_cap);
nitpicker.enqueue<Nitpicker::Session::Command::To_front>(view_handle);
nitpicker.execute();
Loader::Area size = loader.view_size();
Timer::Connection timer;
while(1) {
while (1) {
for (unsigned i = 0; i < 10; i++) {
Nitpicker::Rect rect(Nitpicker::Point(50*i, 50*i),
Nitpicker::Area(geometry.width, geometry.height));
nitpicker.enqueue<Nitpicker::Session::Command::Geometry>(rect);
loader.view_geometry(Loader::Rect(Loader::Point(50*i, 50*i), size),
Loader::Point(0, 0));
timer.msleep(1000);
}
}
sleep_forever();
Genode::sleep_forever();
return 0;
}