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/user_state>
30 #include <l4/mag-gfx/clip_guard>
31 #include <l4/mag-gfx/texture>
32 #include <l4/mag-gfx/factory>
34 #include <l4/cxx/list>
35 #include <l4/cxx/auto_ptr>
43 namespace Mag_server { namespace {
45 using L4Re::Util::Auto_cap;
47 using Mag_gfx::Texture;
51 class Mag_client : public Object, private Plugin
54 Core_api const *_core;
57 Mag_client() : Plugin("Mag client") {}
58 char const *type() const { return "Mag client"; }
59 void start(Core_api *core);
61 int dispatch(l4_umword_t obj, L4::Ipc_iostream &ios);
70 public L4Re::Util::Icu_cap_array_svr<Mag_goos>
73 typedef L4Re::Util::Icu_cap_array_svr<Mag_goos> Icu_svr;
75 Core_api const *_core;
76 L4Re::Util::Auto_cap<L4Re::Dataspace>::Cap _ev_ds;
78 L4Re::Rm::Auto_region<void*> _ev_ds_m;
79 L4Re::Event_buffer _events;
81 typedef std::vector<cxx::Ref_ptr<Client_buffer> > Buffer_vector;
82 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(); }
104 class Client_buffer : public cxx::Ref_obj
107 L4Re::Util::Auto_cap<L4Re::Dataspace>::Cap _ds;
108 L4Re::Rm::Auto_region<void *> _texture_mem;
114 Client_buffer(Core_api const *core, unsigned long size);
116 L4::Cap<L4Re::Dataspace> ds_cap() const { return _ds.get(); }
117 void *local_addr() const { return _texture_mem.get(); }
118 unsigned long size() const { return _size; }
122 class Client_view : public View
125 Core_api const *_core;
126 cxx::Ref_ptr<Client_buffer> _buffer;
131 unsigned long _buf_offset;
135 register Texture *tmp = _front_txt;
136 asm volatile ("" : : : "memory");
137 _front_txt = _back_txt;
142 Client_view(Core_api const *core, Mag_goos *screen);
143 virtual ~Client_view();
145 int dispatch(l4_umword_t obj, L4::Ipc_iostream &ios);
146 void draw(Canvas *, View_stack const *, Mode) const;
147 void handle_event(L4Re::Event_buffer::Event const &e, Point const &mouse);
149 void get_info(L4Re::Video::View::Info *inf) const;
150 void set_info(L4Re::Video::View::Info const &inf,
151 cxx::Ref_ptr<Client_buffer> const &b);
154 Client_view::Client_view(Core_api const *core, Mag_goos *screen)
155 : View(Rect(), F_need_frame), _core(core), _buffer(0), _screen(screen),
158 Pixel_info const *pi = core->user_state()->vstack()->canvas()->type();
160 _front_txt = pi->factory->create_texture(Area(0,0), (void*)1);
161 _back_txt = pi->factory->create_texture(Area(0,0), (void*)1);
164 Client_view::~Client_view()
166 _core->user_state()->forget_view(this);
173 Client_view::get_info(L4Re::Video::View::Info *inf) const
175 using L4Re::Video::Color_component;
176 inf->flags = L4Re::Video::View::F_fully_dynamic;
177 // we do not support chaning the pixel format
178 inf->flags &= ~L4Re::Video::View::F_set_pixel;
183 inf->buffer_offset = _buf_offset;
185 Pixel_info const *pi = 0;
186 pi = _front_txt->type();
188 inf->bytes_per_line = pi->bytes_per_pixel() * _front_txt->size().w();
189 inf->pixel_info = *pi;
192 inf->buffer_index = _buffer->index;
194 inf->buffer_index = ~0;
199 Client_view::set_info(L4Re::Video::View::Info const &inf,
200 cxx::Ref_ptr<Client_buffer> const &b)
202 Pixel_info const *pi = _core->user_state()->vstack()->canvas()->type();
204 bool recalc_height = false;
205 _back_txt->size(_front_txt->size());
206 _back_txt->pixels(_front_txt->pixels());
208 if (inf.has_set_bytes_per_line())
210 _back_txt->size(Area(inf.bytes_per_line / pi->bytes_per_pixel(), 0));
211 recalc_height = true;
214 if (inf.has_set_buffer())
216 _back_txt->pixels((char *)b->local_addr() + _buf_offset);
218 recalc_height = true;
221 if (inf.has_set_buffer_offset())
223 _back_txt->pixels((char *)_buffer->local_addr() + inf.buffer_offset);
224 _buf_offset = inf.buffer_offset;
225 recalc_height = true;
230 unsigned long w = _back_txt->size().w();
231 unsigned long bw = w * pi->bytes_per_pixel();
249 _back_txt->size(Area(w, h));
252 if (_back_txt->size() != _front_txt->size()
253 || _back_txt->pixels() != _front_txt->pixels())
256 if (inf.has_set_position())
257 _core->user_state()->vstack()->viewport(this, Rect(Point(inf.xpos,
258 inf.ypos), Area(inf.width, inf.height)), true);
262 Mag_goos::Mag_goos(Core_api const *core)
263 : Icu_svr(1, &_ev_irq), _core(core)
265 L4Re::Env const *e = L4Re::Env::env();
266 _ev_ds = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
268 chksys(e->mem_alloc()->alloc(L4_PAGESIZE, _ev_ds.get()));
269 chksys(e->rm()->attach(&_ev_ds_m, L4_PAGESIZE, L4Re::Rm::Search_addr, _ev_ds.get()));
271 _events = L4Re::Event_buffer(_ev_ds_m.get(), L4_PAGESIZE);
274 void Mag_client::start(Core_api *core)
277 core->registry()->register_obj(cxx::Ref_ptr<Mag_client>(this), "mag");
278 if (!obj_cap().is_valid())
279 printf("Service registration failed.\n");
281 printf("Plugin: Mag_client service started\n");
285 Mag_client::dispatch(l4_umword_t, L4::Ipc_iostream &ios)
292 case L4::Meta::Protocol:
293 return L4Re::Util::handle_meta_request<L4::Factory>(ios);
294 case L4::Factory::Protocol:
295 if (L4::kobject_typeid<L4Re::Console>()->
296 has_proto(L4::Ipc::read<L4::Factory::Proto>(ios)))
298 cxx::Ref_ptr<Mag_goos> cf(new Mag_goos(_core));
300 _core->registry()->register_obj(cf);
301 cf->obj_cap()->dec_refcnt(1);
303 ios << L4::Ipc::Snd_fpage(cf->obj_cap(), L4_CAP_FPAGE_RWSD);
308 return -L4_EBADPROTO;
313 Mag_client::destroy()
318 Mag_goos::dispatch(l4_umword_t obj, L4::Ipc_iostream &ios)
325 case L4::Meta::Protocol:
326 return L4Re::Util::handle_meta_request<L4Re::Console>(ios);
327 case L4Re::Protocol::Goos:
328 return screen_dispatch(obj, ios);
329 case L4Re::Protocol::Event:
330 return event_dispatch(obj, ios);
332 return Icu_svr::dispatch(obj, ios);
334 return -L4_EBADPROTO;
340 Mag_goos::event_dispatch(l4_umword_t, L4::Ipc_iostream &ios)
346 case L4Re::Event_::Get:
347 ios << L4::Ipc::Snd_fpage(_ev_ds.get().fpage(L4_CAP_FPAGE_RW));
355 Mag_goos::screen_dispatch(l4_umword_t, L4::Ipc_iostream &ios)
362 case ::L4Re::Video::Goos_::Info:
364 using L4Re::Video::Color_component;
365 using L4Re::Video::Goos;
368 Area a = _core->user_state()->vstack()->canvas()->size();
369 Pixel_info const *mag_pi = _core->user_state()->vstack()->canvas()->type();
372 i.flags = Goos::F_pointer
373 | Goos::F_dynamic_views
374 | Goos::F_dynamic_buffers;
376 i.num_static_views = 0;
377 i.num_static_buffers = 0;
378 i.pixel_info = *mag_pi;
385 case L4Re::Video::Goos_::Create_buffer:
390 cxx::Ref_ptr<Client_buffer> b(new Client_buffer(_core, size));
391 _buffers.push_back(b);
392 b->index = _buffers.size() - 1;
394 ios << L4::Ipc::Snd_fpage(b->ds_cap(), L4_CAP_FPAGE_RW);
399 case L4Re::Video::Goos_::Create_view:
401 cxx::Auto_ptr<Client_view> v(new Client_view(_core, this));
403 return _views.size() - 1;
406 case L4Re::Video::Goos_::Get_buffer:
410 if (idx >= _buffers.size())
413 ios << _buffers[idx]->ds_cap();
417 case L4Re::Video::Goos_::View_info:
421 if (idx >= _views.size())
424 Client_view *cv = _views[idx].get();
426 L4Re::Video::View::Info vi;
434 case L4Re::Video::Goos_::View_set_info:
438 if (idx >= _views.size())
441 Client_view *cv = _views[idx].get();
443 L4Re::Video::View::Info vi;
446 cxx::Weak_ptr<Client_buffer> cb(0);
447 if (vi.has_set_buffer())
449 if (vi.buffer_index >= _buffers.size())
452 cb = _buffers[vi.buffer_index];
455 cv->set_info(vi, cb);
459 case L4Re::Video::Goos_::View_stack:
461 Client_view *pivot = 0;
466 ios >> cvi >> pvi >> behind;
468 if (cvi >= _views.size())
471 cv = _views[cvi].get();
473 if (pvi < _views.size())
474 pivot = _views[pvi].get();
479 _core->user_state()->vstack()->push_bottom(cv);
481 _core->user_state()->vstack()->push_top(cv);
484 _core->user_state()->vstack()->stack(cv, pivot, behind);
489 case L4Re::Video::Goos_::View_refresh:
493 ios >> idx >> x >> y >> w >> h;
495 if (idx >= _views.size())
498 Client_view *cv = _views[idx].get();
499 _core->user_state()->vstack()->refresh_view(cv, 0, Rect(cv->p1() + Point(x,y), Area(w,h)));
517 Client_buffer::Client_buffer(Core_api const *, unsigned long size)
518 : _size(l4_round_page(size))
520 L4Re::Rm::Auto_region<void *> dsa;
521 _ds = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
523 L4Re::chksys(L4Re::Env::env()->mem_alloc()->alloc(_size, _ds.get()));
524 L4Re::chksys(L4Re::Env::env()->rm()->attach(&dsa, _size,
525 L4Re::Rm::Search_addr, _ds.get()));
533 Mag_goos::put_event(L4Re::Event_buffer::Event const &ne, bool trigger)
535 if (_events.put(ne) && trigger)
541 Client_view::draw(Canvas *c, View_stack const *, Mode mode) const
543 Canvas::Mix_mode op = mode.flat() ? Canvas::Solid : Canvas::Mixed;
544 Rgb32::Color frame_color = focused() ? Rgb32::White : View::frame_color();
545 if (mode.xray() && !mode.kill() && focused())
551 Clip_guard cg(c, *this);
553 if (!c->clip_valid())
556 Rgb32::Color mix_color = mode.kill() ? kill_color() : Rgb32::Black;
557 c->draw_texture(_front_txt, mix_color, p1(), op);
561 Client_view::handle_event(L4Re::Event_buffer::Event const &e,
564 if (e.payload.type == L4RE_EV_MAX)
566 L4Re::Event_buffer::Event ne;
568 ne.payload.type = L4RE_EV_ABS;
569 ne.payload.code = L4RE_ABS_X;
570 ne.payload.value = mouse.x();
571 ne.payload.stream_id = e.payload.stream_id;
572 _screen->put_event(ne, false);
573 ne.payload.code = L4RE_ABS_Y;
574 ne.payload.value = mouse.y();
575 _screen->put_event(ne, true);
579 _screen->put_event(e, true);
584 static Mag_client _mag_client;