2 * (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3 * Alexander Warg <warg@os.inf.tu-dresden.de>
4 * economic rights: Technische Universität Dresden (Germany)
6 * This file is part of TUD:OS and distributed under the terms of the
7 * GNU General Public License 2.
8 * Please see the COPYING-GPL-2 file for details.
11 #include <l4/re/protocols>
12 #include <l4/re/namespace>
13 #include <l4/re/event_enums.h>
14 #include <l4/cxx/ipc_server>
15 #include <l4/re/error_helper>
17 #include <l4/re/dataspace>
18 #include <l4/re/mem_alloc>
19 #include <l4/re/util/video/goos_svr>
20 #include <l4/re/util/event_svr>
21 #include <l4/re/util/icu_svr>
22 #include <l4/re/video/goos-sys.h>
23 #include <l4/re/video/goos>
24 #include <l4/re/console>
25 #include <l4/re/util/meta>
27 #include <l4/mag/server/plugin>
28 #include <l4/mag/server/object>
29 #include <l4/mag/server/session>
30 #include <l4/mag/server/user_state>
31 #include <l4/mag-gfx/clip_guard>
32 #include <l4/mag-gfx/texture>
33 #include <l4/mag-gfx/factory>
35 #include <l4/cxx/list>
36 #include <l4/cxx/auto_ptr>
44 namespace Mag_server { namespace {
46 using L4Re::Util::Auto_cap;
48 using Mag_gfx::Texture;
52 class Mag_client : public Object, private Plugin
55 Core_api const *_core;
58 Mag_client() : Plugin("Mag client") {}
59 char const *type() const { return "Mag client"; }
60 void start(Core_api *core);
62 int dispatch(l4_umword_t obj, L4::Ipc_iostream &ios);
70 : public Session, public Object,
71 public L4Re::Util::Icu_cap_array_svr<Mag_goos>
74 typedef L4Re::Util::Icu_cap_array_svr<Mag_goos> Icu_svr;
76 Core_api const *_core;
77 L4Re::Util::Auto_cap<L4Re::Dataspace>::Cap _ev_ds;
79 L4Re::Rm::Auto_region<void*> _ev_ds_m;
80 L4Re::Event_buffer _events;
82 typedef std::vector<cxx::Ref_ptr<Client_buffer> > Buffer_vector;
83 typedef std::vector<cxx::Auto_ptr<Client_view> > View_vector;
85 Buffer_vector _buffers;
88 int screen_dispatch(l4_umword_t, L4::Ipc_iostream &ios);
89 int event_dispatch(l4_umword_t, L4::Ipc_iostream &ios);
92 Mag_goos(Core_api const *core);
94 void put_event(L4Re::Event_buffer::Event const &ne, bool trigger);
95 int dispatch(l4_umword_t obj, L4::Ipc_iostream &ios);
97 L4::Cap<void> rcv_cap() const { return _core->rcv_cap(); }
103 class Client_buffer : public cxx::Ref_obj
106 L4Re::Util::Auto_cap<L4Re::Dataspace>::Cap _ds;
107 L4Re::Rm::Auto_region<void *> _texture_mem;
113 Client_buffer(Core_api const *core, unsigned long size);
115 L4::Cap<L4Re::Dataspace> ds_cap() const { return _ds.get(); }
116 void *local_addr() const { return _texture_mem.get(); }
117 unsigned long size() const { return _size; }
121 class Client_view : public View
124 Core_api const *_core;
125 cxx::Ref_ptr<Client_buffer> _buffer;
130 unsigned long _buf_offset;
134 register Texture *tmp = _front_txt;
135 asm volatile ("" : : : "memory");
136 _front_txt = _back_txt;
141 Client_view(Core_api const *core, Mag_goos *screen);
142 virtual ~Client_view();
144 int dispatch(l4_umword_t obj, L4::Ipc_iostream &ios);
145 void draw(Canvas *, View_stack const *, Mode) const;
146 void handle_event(L4Re::Event_buffer::Event const &e, Point const &mouse);
148 void get_info(L4Re::Video::View::Info *inf) const;
149 void set_info(L4Re::Video::View::Info const &inf,
150 cxx::Ref_ptr<Client_buffer> const &b);
152 Session *session() const { return _screen; }
155 Client_view::Client_view(Core_api const *core, Mag_goos *screen)
156 : View(Rect(), F_need_frame), _core(core), _buffer(0), _screen(screen),
159 Pixel_info const *pi = core->user_state()->vstack()->canvas()->type();
161 _front_txt = pi->factory->create_texture(Area(0,0), (void*)1);
162 _back_txt = pi->factory->create_texture(Area(0,0), (void*)1);
163 calc_label_sz(core->label_font());
166 Client_view::~Client_view()
168 if (_screen && _screen->background() == this)
170 // look for other background views below
171 View_stack *vs = _core->user_state()->vstack();
172 // We can either search below this view in the stack, or
173 // we can search from the top of the stack to find the uppermost
174 // view of our session that is tagged as background
175 View *v = vs->next_view(this); // search below this view
176 // View *v = vs->top(); // Search from the top of the stack
177 for (; v; v = vs->next_view(v))
178 if (v != this && v->session() == _screen && v->background())
180 _screen->background(v);
183 _core->user_state()->forget_view(this);
190 Client_view::get_info(L4Re::Video::View::Info *inf) const
192 using L4Re::Video::Color_component;
193 inf->flags = L4Re::Video::View::F_fully_dynamic;
194 // we do not support chaning the pixel format
195 inf->flags &= ~L4Re::Video::View::F_set_pixel;
197 inf->flags |= L4Re::Video::View::F_above;
203 inf->buffer_offset = _buf_offset;
205 Pixel_info const *pi = 0;
206 pi = _front_txt->type();
208 inf->bytes_per_line = pi->bytes_per_pixel() * _front_txt->size().w();
209 inf->pixel_info = *pi;
212 inf->buffer_index = _buffer->index;
214 inf->buffer_index = ~0;
219 Client_view::set_info(L4Re::Video::View::Info const &inf,
220 cxx::Ref_ptr<Client_buffer> const &b)
222 Pixel_info const *pi = _core->user_state()->vstack()->canvas()->type();
224 bool recalc_height = false;
225 _back_txt->size(_front_txt->size());
226 _back_txt->pixels(_front_txt->pixels());
228 if (inf.flags & L4Re::Video::View::F_set_flags)
229 set_above(inf.flags & L4Re::Video::View::F_above);
231 if (inf.flags & L4Re::Video::View::F_set_background)
233 _core->user_state()->vstack()->push_bottom(this);
235 _screen->background(this);
238 if (inf.has_set_bytes_per_line())
240 _back_txt->size(Area(inf.bytes_per_line / pi->bytes_per_pixel(), 0));
241 recalc_height = true;
244 if (inf.has_set_buffer())
246 _back_txt->pixels((char *)b->local_addr() + _buf_offset);
248 recalc_height = true;
253 _back_txt->size(Area(0, 0));
254 _back_txt->pixels((char *)0);
255 _front_txt->size(Area(0, 0));
256 _front_txt->pixels((char *)0);
259 if (inf.has_set_buffer_offset() && _buffer)
261 _back_txt->pixels((char *)_buffer->local_addr() + inf.buffer_offset);
262 _buf_offset = inf.buffer_offset;
263 recalc_height = true;
266 if (recalc_height && _buffer)
268 unsigned long w = _back_txt->size().w();
269 unsigned long bw = w * pi->bytes_per_pixel();
287 _back_txt->size(Area(w, h));
290 if (_back_txt->size() != _front_txt->size()
291 || _back_txt->pixels() != _front_txt->pixels())
294 if (inf.has_set_position())
295 _core->user_state()->vstack()->viewport(this, Rect(Point(inf.xpos,
296 inf.ypos), Area(inf.width, inf.height)), true);
300 Mag_goos::Mag_goos(Core_api const *core)
301 : Icu_svr(1, &_ev_irq), _core(core)
303 L4Re::Env const *e = L4Re::Env::env();
304 _ev_ds = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
306 chksys(e->mem_alloc()->alloc(L4_PAGESIZE, _ev_ds.get()));
307 chksys(e->rm()->attach(&_ev_ds_m, L4_PAGESIZE, L4Re::Rm::Search_addr, _ev_ds.get()));
309 _events = L4Re::Event_buffer(_ev_ds_m.get(), L4_PAGESIZE);
312 void Mag_client::start(Core_api *core)
315 core->registry()->register_obj(cxx::Ref_ptr<Mag_client>(this), "mag");
316 if (!obj_cap().is_valid())
317 printf("Service registration failed.\n");
319 printf("Plugin: Mag_client service started\n");
323 Mag_client::dispatch(l4_umword_t, L4::Ipc_iostream &ios)
330 case L4::Meta::Protocol:
331 return L4Re::Util::handle_meta_request<L4::Factory>(ios);
332 case L4::Factory::Protocol:
333 if (L4::kobject_typeid<L4Re::Console>()->
334 has_proto(L4::Ipc::read<L4::Factory::Proto>(ios)))
336 L4::Ipc::Istream_copy cp_is = ios;
338 cxx::Ref_ptr<Mag_goos> cf(new Mag_goos(_core));
339 _core->set_session_options(cf.get(), cp_is);
341 _core->register_session(cf.get());
342 _core->registry()->register_obj(cf);
343 cf->obj_cap()->dec_refcnt(1);
345 ios << L4::Ipc::Snd_fpage(cf->obj_cap(), L4_CAP_FPAGE_RWSD);
350 return -L4_EBADPROTO;
355 Mag_client::destroy()
360 Mag_goos::dispatch(l4_umword_t obj, L4::Ipc_iostream &ios)
367 case L4::Meta::Protocol:
368 return L4Re::Util::handle_meta_request<L4Re::Console>(ios);
369 case L4Re::Protocol::Goos:
370 return screen_dispatch(obj, ios);
371 case L4Re::Protocol::Event:
372 return event_dispatch(obj, ios);
374 return Icu_svr::dispatch(obj, ios);
376 return -L4_EBADPROTO;
382 Mag_goos::event_dispatch(l4_umword_t, L4::Ipc_iostream &ios)
388 case L4Re::Event_::Get:
389 ios << L4::Ipc::Snd_fpage(_ev_ds.get().fpage(L4_CAP_FPAGE_RW));
397 Mag_goos::screen_dispatch(l4_umword_t, L4::Ipc_iostream &ios)
404 case ::L4Re::Video::Goos_::Info:
406 using L4Re::Video::Color_component;
407 using L4Re::Video::Goos;
410 Area a = _core->user_state()->vstack()->canvas()->size();
411 Pixel_info const *mag_pi = _core->user_state()->vstack()->canvas()->type();
414 i.flags = Goos::F_pointer
415 | Goos::F_dynamic_views
416 | Goos::F_dynamic_buffers;
418 i.num_static_views = 0;
419 i.num_static_buffers = 0;
420 i.pixel_info = *mag_pi;
427 case L4Re::Video::Goos_::Create_buffer:
432 cxx::Ref_ptr<Client_buffer> b(new Client_buffer(_core, size));
433 _buffers.push_back(b);
434 b->index = _buffers.size() - 1;
436 ios << L4::Ipc::Snd_fpage(b->ds_cap(), L4_CAP_FPAGE_RW);
441 case L4Re::Video::Goos_::Create_view:
443 cxx::Auto_ptr<Client_view> v(new Client_view(_core, this));
445 for (View_vector::iterator i = _views.begin(); i != _views.end();
454 return _views.size() - 1;
457 case L4Re::Video::Goos_::Delete_view:
461 if (idx >= _views.size())
464 _views[idx].reset(0);
468 case L4Re::Video::Goos_::Get_buffer:
472 if (idx >= _buffers.size())
475 ios << _buffers[idx]->ds_cap();
479 case L4Re::Video::Goos_::View_info:
483 if (idx >= _views.size())
486 Client_view *cv = _views[idx].get();
488 L4Re::Video::View::Info vi;
496 case L4Re::Video::Goos_::View_set_info:
500 if (idx >= _views.size())
503 Client_view *cv = _views[idx].get();
505 L4Re::Video::View::Info vi;
508 cxx::Weak_ptr<Client_buffer> cb(0);
509 if (vi.has_set_buffer())
511 if (vi.buffer_index >= _buffers.size())
514 cb = _buffers[vi.buffer_index];
517 cv->set_info(vi, cb);
521 case L4Re::Video::Goos_::View_stack:
523 Client_view *pivot = 0;
528 ios >> cvi >> pvi >> behind;
530 if (cvi >= _views.size())
533 cv = _views[cvi].get();
535 if (pvi < _views.size())
536 pivot = _views[pvi].get();
541 _core->user_state()->vstack()->push_bottom(cv);
543 _core->user_state()->vstack()->push_top(cv);
546 _core->user_state()->vstack()->stack(cv, pivot, behind);
551 case L4Re::Video::Goos_::View_refresh:
555 ios >> idx >> x >> y >> w >> h;
557 if (idx >= _views.size())
560 Client_view *cv = _views[idx].get();
561 _core->user_state()->vstack()->refresh_view(cv, 0, Rect(cv->p1() + Point(x,y), Area(w,h)));
566 case L4Re::Video::Goos_::Screen_refresh:
569 ios >> x >> y >> w >> h;
571 _core->user_state()->vstack()->refresh_view(0, 0, Rect(Point(x,y), Area(w,h)));
589 Client_buffer::Client_buffer(Core_api const *, unsigned long size)
590 : _size(l4_round_page(size))
592 L4Re::Rm::Auto_region<void *> dsa;
593 _ds = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
595 L4Re::chksys(L4Re::Env::env()->mem_alloc()->alloc(_size, _ds.get()));
596 L4Re::chksys(L4Re::Env::env()->rm()->attach(&dsa, _size,
597 L4Re::Rm::Search_addr, _ds.get()));
605 Mag_goos::put_event(L4Re::Event_buffer::Event const &ne, bool trigger)
607 if (_events.put(ne) && trigger)
613 Client_view::draw(Canvas *c, View_stack const *, Mode mode) const
615 Canvas::Mix_mode op = mode.flat() ? Canvas::Solid : Canvas::Mixed;
616 Rgb32::Color frame_color = focused() ? Rgb32::White : View::frame_color();
617 if (mode.xray() && !mode.kill() && focused())
620 Clip_guard cg(c, *this);
622 if (!c->clip_valid())
625 Rgb32::Color mix_color = /*mode.kill() ? kill_color() :*/ session()->color();
629 c->draw_texture(_front_txt, mix_color, p1(), op);
630 s = _front_txt->size();
635 c->draw_box(Rect(p1() + Point(0, s.h()), Area(size().w(), r.h())), mix_color);
637 if (r.w() > 0 && size().h() != r.h())
638 c->draw_box(Rect(p1() + Point(s.w(), 0), Area(r.w(), s.h())), mix_color);
642 Client_view::handle_event(L4Re::Event_buffer::Event const &e,
645 if (e.payload.type == L4RE_EV_MAX)
647 L4Re::Event_buffer::Event ne;
649 ne.payload.type = L4RE_EV_ABS;
650 ne.payload.code = L4RE_ABS_X;
651 ne.payload.value = mouse.x();
652 ne.payload.stream_id = e.payload.stream_id;
653 _screen->put_event(ne, false);
654 ne.payload.code = L4RE_ABS_Y;
655 ne.payload.value = mouse.y();
656 _screen->put_event(ne, true);
660 _screen->put_event(e, true);
665 static Mag_client _mag_client;