]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/mag/server/src/main.cc
update
[l4.git] / l4 / pkg / mag / server / src / main.cc
1 /*
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)
5  *
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.
9  */
10 #include <l4/mag-gfx/geometry>
11 #include <l4/mag-gfx/canvas>
12 #include "factory"
13
14 #include <l4/util/util.h>
15
16 #include <l4/cxx/iostream>
17 #include <l4/cxx/exceptions>
18 #include <l4/re/util/cap_alloc>
19 #include <l4/re/error_helper>
20 #include <l4/re/env>
21 #include <l4/re/rm>
22 #include <l4/re/video/goos>
23 #include <l4/re/util/video/goos_fb>
24
25 #include <cassert>
26 #include <cstdio>
27 #include <cstring>
28
29 #include "background.h"
30 #include "big_mouse.h"
31 #include "input_driver"
32 #include "object_gc.h"
33
34 #include "plugin"
35
36 #include <dlfcn.h>
37
38 using namespace Mag_server;
39
40 static Core_api *_core_api;
41
42 namespace Mag_server {
43
44 class Plugin_manager
45 {
46 public:
47   static void start_plugins(Core_api *core)
48   {
49     for (Plugin *p = Plugin::_first; p; p = p->_next)
50       if (!p->started())
51         p->start(core);
52   }
53 };
54
55 }
56
57 namespace {
58
59
60 class My_reg : public Registry, private Object_gc
61 {
62 private:
63   class Del_handler : public L4::Server_object
64   {
65   private:
66     Object_gc *gc;
67
68   public:
69     explicit Del_handler(Object_gc *gc) : gc(gc) {}
70
71     int dispatch(l4_umword_t, L4::Ipc_iostream &s)
72     {
73       l4_msgtag_t t;
74       s >> t;
75       if (t.label() != L4_PROTO_IRQ)
76         return -L4_EBADPROTO;
77
78       gc->gc_step();
79       return 0;
80     }
81   };
82
83   L4::Cap<L4::Irq> _del_irq;
84
85 public:
86   My_reg() : Registry()
87   {
88     _del_irq = register_irq_obj(new Del_handler(this));
89     assert (_del_irq);
90     _server->register_del_irq(_del_irq);
91   };
92
93   void add_gc_obj(Object *o)
94   {
95     L4::Cap<L4::Kobject> c(o->obj_cap());
96     Object_gc::add_obj(o);
97   }
98 };
99
100
101 static void
102 poll_input(Core_api *core)
103 {
104   for (Input_source *i = core->input_sources(); i; i = i->next())
105       i->poll_events();
106 }
107
108 static L4::Cap<void> rcv_cap;
109
110 class Loop_hooks : public L4::Ipc_svr::Ignore_errors
111 {
112 public:
113   l4_kernel_clock_t to;
114   Loop_hooks()
115   {
116     to = l4re_kip()->clock + 40000;
117   }
118
119   l4_timeout_t timeout()
120   { return l4_timeout(L4_IPC_TIMEOUT_0, l4_timeout_abs(to, 8)); }
121
122   void setup_wait(L4::Ipc_istream &istr, L4::Ipc_svr::Reply_mode reply_mode)
123   {
124     if (to < l4re_kip()->clock
125         && reply_mode == L4::Ipc_svr::Reply_separate)
126     {
127       poll_input(_core_api);
128       _core_api->user_state()->vstack()->flush();
129       to += 40000;
130       while (to - 10000 < l4re_kip()->clock)
131         to += 20000;
132     }
133
134     istr.reset();
135     istr << L4::Small_buf(rcv_cap.cap(), L4_RCV_ITEM_LOCAL_ID);
136     l4_utcb_br_u(istr.utcb())->bdr = 0;
137     l4_timeout_abs(to, 8);
138   }
139
140   L4::Ipc_svr::Reply_mode before_reply(long, L4::Ipc_iostream &)
141   {
142     if (to < l4re_kip()->clock)
143       return L4::Ipc_svr::Reply_separate;
144     return L4::Ipc_svr::Reply_compound;
145   }
146 };
147
148 static My_reg registry;
149 static L4::Server<Loop_hooks> server(l4_utcb());
150
151 using L4Re::Util::Auto_cap;
152 using L4Re::chksys;
153 using L4Re::chkcap;
154 #if 0
155 static void test_texture(Texture *t)
156 {
157   char *tb = (char *)t->pixels();
158   for (int y = 0; y < t->size().h(); ++y)
159     for (int x = 0; x < t->size().w(); ++x)
160       {
161         t->type()->set(tb, Pixel_info::Col(x*400, y*300, x*y, 0));
162         tb += t->type()->bytes;
163       }
164 }
165 #endif
166
167 int load_plugin(Core_api *core_api, char const *name)
168 {
169   static char const *const pfx = "libmag-";
170   static char const *const sfx = ".so";
171   char *n = new char [strlen(name) + strlen(pfx) + strlen(sfx) + 1];
172   strcpy(n, pfx);
173   strcpy(n + strlen(pfx), name);
174   strcpy(n + strlen(pfx) + strlen(name), sfx);
175
176   printf("loading '%s'\n", n);
177
178   void *pl = dlopen(n, RTLD_LAZY);
179   if (!pl)
180     {
181       delete [] n;
182       printf("ERROR: loading '%s': %s\n", n, dlerror());
183       return -1;
184     }
185   else
186     {
187       void (*ini)(Core_api*) = (void (*)(Core_api*))dlsym(pl, "init_plugin");
188       ini(core_api);
189     }
190   delete [] n;
191   return 0;
192 }
193
194 int run(int argc, char const *argv[])
195 {
196   printf("Hello from MAG\n");
197   L4Re::Env const *env = L4Re::Env::env();
198
199   L4::Cap<L4Re::Video::Goos> fb
200     = chkcap(env->get_cap<L4Re::Video::Goos>("fb"), "requesting frame-buffer", 0);
201
202   L4Re::Util::Video::Goos_fb goos_fb(fb);
203   L4Re::Video::View::Info view_i;
204   chksys(goos_fb.view_info(&view_i), "requesting frame-buffer info");
205
206   L4Re::Rm::Auto_region<char *> fb_addr;
207   chksys(env->rm()->attach(&fb_addr, goos_fb.buffer()->size(),
208         L4Re::Rm::Search_addr, goos_fb.buffer(), 0, L4_SUPERPAGESHIFT));
209
210   printf("mapped frame buffer at %p\n", fb_addr.get());
211
212   Screen_factory *f = dynamic_cast<Screen_factory*>(Screen_factory::set.find(view_i.pixel_info));
213   if (!f)
214     {
215       printf("ERROR: could not start screen driver for given video mode.\n"
216              "       Maybe unsupoported pixel format... exiting\n");
217       exit(1);
218     }
219
220   Canvas *screen = f->create_canvas(fb_addr.get() + view_i.buffer_offset,
221       Area(view_i.width, view_i.height), view_i.bytes_per_line);
222
223   view_i.dump(L4::cout)
224     << "  memory " << (void*)fb_addr.get()
225     << '-' << (void*)(fb_addr.get() + goos_fb.buffer()->size()) << '\n';
226
227   if (!screen)
228     {
229       printf("ERROR: could not start screen driver for given video mode.\n"
230              "       Maybe unsupoported pixel format... exiting\n");
231       exit(1);
232     }
233
234   rcv_cap = L4Re::Util::cap_alloc.alloc<void>();
235   if (!rcv_cap.is_valid())
236     {
237       printf("ERROR: Out of caps\n");
238       exit(1);
239     }
240
241   View *cursor = f->create_cursor(big_mouse);
242   Background bg(screen->size());
243
244   L4Re::Video::View *screen_view = 0;
245
246     {
247       L4Re::Video::Goos::Info i;
248       goos_fb.goos()->info(&i);
249       if (!i.auto_refresh())
250         screen_view = goos_fb.view();
251     }
252   
253   static User_state user_state(screen, screen_view, cursor, &bg);
254   static Core_api core_api(&registry, &user_state, rcv_cap, fb);
255
256   Plugin_manager::start_plugins(&core_api);
257
258   for (int i = 1; i < argc; ++i)
259     load_plugin(&core_api, argv[i]);
260
261   _core_api = &core_api;
262
263   server.loop(registry);
264
265   return 0;
266 }
267 }
268
269 int main(int argc, char const *argv[])
270 {
271   try
272     {
273       return run(argc, argv);
274     }
275   catch (L4::Runtime_error const &e)
276     {
277       L4::cerr << "Error: " << e << '\n';
278     }
279   catch (L4::Base_exception const &e)
280     {
281       L4::cerr << "Error: " << e << '\n';
282     }
283   catch (std::exception const &e)
284     {
285       L4::cerr << "Error: " << e.what() << '\n';
286     }
287
288   return -1;
289 }