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