]> 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 <lua.h>
26 #include <lauxlib.h>
27 #include <lualib.h>
28
29 #include <cassert>
30 #include <cstdio>
31 #include <cstring>
32
33 #include <unistd.h>
34
35 #include "background.h"
36 #include "big_mouse.h"
37 #include "input_driver"
38 #include "object_gc.h"
39
40 #include "core_api"
41
42 #include <dlfcn.h>
43
44 using namespace Mag_server;
45
46 static Core_api_impl *_core_api;
47 extern char const _binary_mag_lua_start[];
48 extern char const _binary_mag_lua_end[];
49 extern char const _binary_default_tff_start[];
50
51 namespace Mag_server {
52
53 class Plugin_manager
54 {
55 public:
56   static void start_plugins(Core_api *core)
57   {
58     for (Plugin *p = Plugin::_first; p; p = p->_next)
59       if (!p->started())
60         p->start(core);
61   }
62 };
63
64 }
65
66 namespace {
67
68
69 class My_reg : public Registry, private Object_gc
70 {
71 private:
72   class Del_handler : public L4::Server_object
73   {
74   private:
75     Object_gc *gc;
76
77   public:
78     explicit Del_handler(Object_gc *gc) : gc(gc) {}
79
80     int dispatch(l4_umword_t, L4::Ipc_iostream &s)
81     {
82       l4_msgtag_t t;
83       s >> t;
84       if (t.label() != L4_PROTO_IRQ)
85         return -L4_EBADPROTO;
86
87       gc->gc_step();
88       return 0;
89     }
90   };
91
92   L4::Cap<L4::Irq> _del_irq;
93
94 public:
95   My_reg() : Registry()
96   {
97     _del_irq = register_irq_obj(new Del_handler(this));
98     assert (_del_irq);
99     _server->register_del_irq(_del_irq);
100   };
101
102   void add_gc_obj(Object *o)
103   {
104     L4::Cap<L4::Kobject> c(o->obj_cap());
105     Object_gc::add_obj(o);
106   }
107 };
108
109
110 static void
111 poll_input(Core_api_impl *core)
112 {
113   for (Input_source *i = core->input_sources(); i; i = i->next())
114       i->poll_events();
115 }
116
117 static L4::Cap<void> rcv_cap;
118
119 class Loop_hooks : public L4::Ipc_svr::Ignore_errors
120 {
121 public:
122   l4_kernel_clock_t to;
123   Loop_hooks()
124   {
125     to = l4re_kip()->clock + 40000;
126   }
127
128   l4_timeout_t timeout()
129   { return l4_timeout(L4_IPC_TIMEOUT_0, l4_timeout_abs(to, 8)); }
130
131   void setup_wait(L4::Ipc_istream &istr, L4::Ipc_svr::Reply_mode reply_mode)
132   {
133     if (to < l4re_kip()->clock
134         && reply_mode == L4::Ipc_svr::Reply_separate)
135     {
136       poll_input(_core_api);
137       _core_api->user_state()->vstack()->flush();
138       _core_api->tick();
139       to += 40000;
140       while (to - 10000 < l4re_kip()->clock)
141         to += 20000;
142     }
143
144     istr.reset();
145     istr << L4::Small_buf(rcv_cap.cap(), L4_RCV_ITEM_LOCAL_ID);
146     l4_utcb_br_u(istr.utcb())->bdr = 0;
147     l4_timeout_abs(to, 8);
148   }
149
150   L4::Ipc_svr::Reply_mode before_reply(long, L4::Ipc_iostream &)
151   {
152     if (to < l4re_kip()->clock)
153       return L4::Ipc_svr::Reply_separate;
154     return L4::Ipc_svr::Reply_compound;
155   }
156 };
157
158 static My_reg registry;
159 static L4::Server<Loop_hooks> server(l4_utcb());
160
161 using L4Re::Util::Auto_cap;
162 using L4Re::chksys;
163 using L4Re::chkcap;
164 #if 0
165 static void test_texture(Texture *t)
166 {
167   char *tb = (char *)t->pixels();
168   for (int y = 0; y < t->size().h(); ++y)
169     for (int x = 0; x < t->size().w(); ++x)
170       {
171         t->type()->set(tb, Pixel_info::Col(x*400, y*300, x*y, 0));
172         tb += t->type()->bytes;
173       }
174 }
175 #endif
176
177 int load_lua_plugin(Core_api *core_api, char const *name)
178 {
179   char const *n = name;
180
181   if (access(n, F_OK) != 0)
182     return 1;
183
184   printf("loading '%s'\n", n);
185
186   lua_State *_l = core_api->lua_state();
187   int err = luaL_dofile(_l, n);
188   if (err)
189     {
190       printf("ERROR: loading '%s': %s\n", n, lua_tostring(_l, -1));
191       lua_pop(_l, lua_gettop(_l));
192       return -1;
193     }
194
195   lua_pop(_l, lua_gettop(_l));
196   return 0;
197 }
198
199 int load_so_plugin(Core_api *core_api, char const *name)
200 {
201   static char const *const pfx = "libmag-";
202   static char const *const sfx = ".so";
203   char *n = new char [strlen(name) + strlen(pfx) + strlen(sfx) + 1];
204   strcpy(n, pfx);
205   strcpy(n + strlen(pfx), name);
206   strcpy(n + strlen(pfx) + strlen(name), sfx);
207
208   printf("loading '%s'\n", n);
209
210   void *pl = dlopen(n, RTLD_LAZY);
211   if (!pl)
212     {
213       delete [] n;
214       printf("ERROR: loading '%s': %s\n", n, dlerror());
215       return -1;
216     }
217   else
218     {
219       void (*ini)(Core_api*) = (void (*)(Core_api*))dlsym(pl, "init_plugin");
220       ini(core_api);
221     }
222   delete [] n;
223   return 0;
224 }
225
226 static const luaL_Reg libs[] =
227 {
228   { "", luaopen_base },
229 // { LUA_IOLIBNAME, luaopen_io },
230   { LUA_STRLIBNAME, luaopen_string },
231   {LUA_LOADLIBNAME, luaopen_package},
232   {LUA_DBLIBNAME, luaopen_debug},
233   { NULL, NULL }
234 };
235
236 int run(int argc, char const *argv[])
237 {
238   printf("Hello from MAG\n");
239   L4Re::Env const *env = L4Re::Env::env();
240
241   L4::Cap<L4Re::Video::Goos> fb
242     = chkcap(env->get_cap<L4Re::Video::Goos>("fb"), "requesting frame-buffer", 0);
243
244   L4Re::Util::Video::Goos_fb goos_fb(fb);
245   L4Re::Video::View::Info view_i;
246   chksys(goos_fb.view_info(&view_i), "requesting frame-buffer info");
247
248   L4Re::Rm::Auto_region<char *> fb_addr;
249   chksys(env->rm()->attach(&fb_addr, goos_fb.buffer()->size(),
250         L4Re::Rm::Search_addr, goos_fb.buffer(), 0, L4_SUPERPAGESHIFT));
251
252   printf("mapped frame buffer at %p\n", fb_addr.get());
253
254   Screen_factory *f = dynamic_cast<Screen_factory*>(Screen_factory::set.find(view_i.pixel_info));
255   if (!f)
256     {
257       printf("ERROR: could not start screen driver for given video mode.\n"
258              "       Maybe unsupoported pixel format... exiting\n");
259       exit(1);
260     }
261
262   Canvas *screen = f->create_canvas(fb_addr.get() + view_i.buffer_offset,
263       Area(view_i.width, view_i.height), view_i.bytes_per_line);
264
265   view_i.dump(L4::cout)
266     << "  memory " << (void*)fb_addr.get()
267     << '-' << (void*)(fb_addr.get() + goos_fb.buffer()->size()) << '\n';
268
269   if (!screen)
270     {
271       printf("ERROR: could not start screen driver for given video mode.\n"
272              "       Maybe unsupoported pixel format... exiting\n");
273       exit(1);
274     }
275
276   rcv_cap = L4Re::Util::cap_alloc.alloc<void>();
277   if (!rcv_cap.is_valid())
278     {
279       printf("ERROR: Out of caps\n");
280       exit(1);
281     }
282
283   View *cursor = f->create_cursor(big_mouse);
284   Background bg(screen->size());
285
286   L4Re::Video::View *screen_view = 0;
287
288     {
289       L4Re::Video::Goos::Info i;
290       goos_fb.goos()->info(&i);
291       if (!i.auto_refresh())
292         screen_view = goos_fb.view();
293     }
294
295   lua_State *lua = luaL_newstate();
296
297   if (!lua)
298     {
299       printf("ERROR: cannot allocate Lua state\n");
300       exit(1);
301     }
302
303   for (int i = 0; libs[i].func; ++i)
304     {
305       lua_pushcfunction(lua, libs[i].func);
306       lua_pushstring(lua,libs[i].name);
307       lua_call(lua, 1, 0);
308     }
309
310   int err;
311   if ((err = luaL_loadbuffer(lua, _binary_mag_lua_start, _binary_mag_lua_end - _binary_mag_lua_start, "@mag.lua")))
312     {
313       fprintf(stderr, "lua error: %s.\n", lua_tostring(lua, -1));
314       lua_pop(lua, lua_gettop(lua));
315       if (err == LUA_ERRSYNTAX)
316         throw L4::Runtime_error(L4_EINVAL, lua_tostring(lua, -1));
317       else
318         throw L4::Out_of_memory(lua_tostring(lua, -1));
319     }
320
321   if ((err = lua_pcall(lua, 0, 1, 0)))
322     {
323       fprintf(stderr, "lua error: %s.\n", lua_tostring(lua, -1));
324       lua_pop(lua, lua_gettop(lua));
325       if (err == LUA_ERRSYNTAX)
326         throw L4::Runtime_error(L4_EINVAL, lua_tostring(lua, -1));
327       else
328         throw L4::Out_of_memory(lua_tostring(lua, -1));
329     }
330
331   lua_pop(lua, lua_gettop(lua));
332   static Font label_font(&_binary_default_tff_start[0]);
333   static View_stack vstack(screen, screen_view, &bg, &label_font);
334   static User_state user_state(lua, &vstack, cursor);
335   static Core_api_impl core_api(&registry, lua, &user_state, rcv_cap, fb, &label_font);
336
337   Plugin_manager::start_plugins(&core_api);
338
339   for (int i = 1; i < argc; ++i)
340     {
341       if (load_lua_plugin(&core_api, argv[i]) == 1)
342         load_so_plugin(&core_api, argv[i]);
343     }
344
345   _core_api = &core_api;
346
347   server.loop(registry);
348
349   return 0;
350 }
351 }
352
353 int main(int argc, char const *argv[])
354 {
355   try
356     {
357       return run(argc, argv);
358     }
359   catch (L4::Runtime_error const &e)
360     {
361       L4::cerr << "Error: " << e << '\n';
362     }
363   catch (L4::Base_exception const &e)
364     {
365       L4::cerr << "Error: " << e << '\n';
366     }
367   catch (std::exception const &e)
368     {
369       L4::cerr << "Error: " << e.what() << '\n';
370     }
371
372   return -1;
373 }