5 #include <l4/re/util/debug>
7 #include <l4/re/console>
10 #include <l4/re/error_helper>
11 #include <l4/re/util/cap_alloc>
12 #include <l4/re/video/goos>
14 #include <l4/scout-gfx/redraw_manager>
19 #include <semaphore.h>
22 #include <l4/re/event_enums.h>
23 #include <l4/re/event>
24 #include <l4/sys/factory>
25 #include <l4/scout-gfx/redraw_manager>
26 #include <l4/scout-gfx/user_state>
30 using L4Re::Util::Auto_cap;
39 { sem_init(&_s, 0, 0); }
41 void up() { sem_post(&_s); }
42 void down() { sem_wait(&_s); }
44 ~Semaphore() { sem_destroy(&_s); }
55 { pthread_mutex_init(&_m, NULL); }
58 { pthread_mutex_destroy(&_m); }
61 { pthread_mutex_lock(&_m); }
64 { pthread_mutex_unlock(&_m); }
68 template< typename L >
75 explicit Lock_guard(L &l) : _l(l) { _l.lock(); }
76 ~Lock_guard() { _l.unlock(); }
86 enum { queue_size = 1024 };
91 Lock _head_lock; /* synchronize add */
93 Scout_gfx::Event _queue[queue_size];
100 Eventqueue(): _head(0), _tail(0)
102 memset(_queue, 0, sizeof(_queue));
105 void add(Scout_gfx::Event const &ev)
107 Lock_guard<Lock> lock_guard(_head_lock);
109 if ((_head + 1)%queue_size != _tail)
113 _head = (_head + 1)%queue_size;
118 void get(Scout_gfx::Event *dst_ev)
121 *dst_ev = _queue[_tail];
122 _tail = (_tail + 1)%queue_size;
125 int pending() { return _head != _tail; }
133 using Mag_gfx::Point;
140 Auto_cap<L4Re::Dataspace>::Cap _ev_ds;
141 Auto_cap<L4::Irq>::Cap _ev_irq;
142 L4Re::Rm::Auto_region<void *> _ev_ds_addr;
143 L4Re::Event_buffer _evb;
148 l4_uint64_t _timer_tick;
150 void _set_ev(Scout_gfx::Event &ev)
152 ev.key_cnt = _key_cnt;
156 void _import_events()
158 using Scout_gfx::Event;
159 typedef L4Re::Event_buffer::Event Re_ev;
161 for (Re_ev *re = _evb.next(); re; re->free(), re = _evb.next())
165 switch (re->payload.type)
168 switch (re->payload.value)
170 case 1: ++_key_cnt; ev.type = Event::PRESS; break;
171 case 0: --_key_cnt; ev.type = Event::RELEASE; break;
178 ev.code = re->payload.code;
184 switch (re->payload.code)
187 _m = Point(re->payload.value, _m.y());
190 _m = Point(_m.x(), re->payload.value);
199 ev.type = Event::MOTION;
207 ev.type = Event::WHEEL;
209 switch (re->payload.code)
213 ev.wy = re->payload.value;
215 case L4RE_REL_HWHEEL:
217 ev.wx = re->payload.value;
232 static void *_tstart(void *t)
234 reinterpret_cast<Timer_thread*>(t)->entry();
240 l4_uint64_t ticks() const { return _timer_tick; }
245 * Start thread immediately on construction.
248 : _key_cnt(0), _timer_tick(0)
251 void start(L4::Cap<L4Re::Event> const &e)
254 using L4Re::Util::cap_alloc;
257 _ev_ds = cap_alloc.alloc<L4Re::Dataspace>();
258 _ev_irq = cap_alloc.alloc<L4::Irq>();
259 chksys(L4Re::Env::env()->factory()->create(_ev_irq.get()));
260 chksys(e->get_buffer(_ev_ds.get()));
261 chksys(L4Re::Env::env()->rm()->attach(&_ev_ds_addr, _ev_ds->size(),
262 L4Re::Rm::Search_addr, _ev_ds.get(), 0, L4_PAGESHIFT));
264 _evb = L4Re::Event_buffer(_ev_ds_addr.get(), _ev_ds->size());
266 pthread_create(&_th, NULL, &_tstart, this);
274 ev.assign(Scout_gfx::Event::TIMER, _m, 0);
287 class Re_view : public Scout_gfx::View
291 Scout_gfx::Redraw_manager *_rdm;
292 Mag_gfx::Canvas *_canvas;
293 L4Re::Video::View _view;
294 L4Re::Video::View::Info _view_info;
296 unsigned long _buffer_offset;
300 Re_view(Rect const &r, Rect const &ol, Scout_gfx::Redraw_manager *rdm,
301 Mag_gfx::Canvas *canvas, L4Re::Video::View const &v,
302 unsigned long buffer_offset);
304 * View geometry accessor functions
306 virtual Rect geometry() const { return _v; }
308 virtual void redraw(Rect const &r)
309 { _rdm->request(r-_v.p1()); }
311 void scr_refresh(Rect const &r)
312 { _view.refresh(r.x1(), r.y1(), r.w(), r.h()); }
314 void set_buf_pos(unsigned long offset)
316 _buffer_offset = offset;
317 _view.set_viewport(_v.x1(), _v.y1(), _v.w(), _v.h(), offset);
320 * Define geometry of viewport on screen
322 * The specified area is relative to the screen
325 virtual Rect set_geometry(Rect const &pos, bool do_redraw)
327 // printf("view geometry: %d,%d-%d,%d %d\n", pos.x1(), pos.y1(), pos.x2(), pos.y2(), do_redraw);
328 if (!_view_info.has_set_position())
332 _v = pos; //Rect(Point(0,0), scr_size());
335 //_rdm->request(old_pos);
336 _view.set_viewport(_v.x1(), _v.y1(), _v.w(), _v.h(), _buffer_offset);
345 * Bring Scouts view ontop
347 virtual void top() { _view.push_top(); }
349 void set_view_info(L4Re::Video::View::Info const &vi)
352 L4Re::Video::View::Info const *view_info() const
353 { return &_view_info; }
355 Mag_gfx::Pixel_info const *pixel_info() const
356 { return _canvas->type(); }
359 Re_view::Re_view(Rect const &r, Rect const &ol, Scout_gfx::Redraw_manager *rdm,
360 Mag_gfx::Canvas *canvas, L4Re::Video::View const &v, unsigned long buffer_offset)
361 : _v(r & ol), _rdm(rdm), _canvas(canvas), _view(v), _buffer_offset(buffer_offset)
365 class Re_ust : public Scout_gfx::User_state
368 void draw(Mag_gfx::Canvas *c, Mag_gfx::Point const &p)
370 for (Scout_gfx::Widget *e = _first; e; e = e->next)
375 class Re_pf : public Platform, public Scout_gfx::Screen_update
379 L4Re::Video::Goos::Info _scr_info;
380 L4::Cap<L4Re::Console> _screen;
381 Auto_cap<L4Re::Dataspace>::Cap _fb_ds;
382 L4Re::Rm::Auto_region<char *> _fb_addr;
389 Scout_gfx::Redraw_manager _rdm;
391 Mag_gfx::Canvas *_canvas;
399 Re_pf(Rect const &sz);
400 Mag_gfx::Pixel_info const *pixel_info() const
401 { return _canvas->type(); }
403 int max_num_views() { return 1; }
404 Scout_gfx::View *create_view(Rect const &/*r*/)
409 virtual int initialized()
413 * Request screen width and height
415 virtual Area scr_size() { return _size; }
420 * Get timer ticks in miilliseconds
422 virtual unsigned long timer_ticks() { return _timer.ticks(); }
425 * Request if an event is pending
427 * \retval 1 event is pending
428 * \retval 0 no event pending
430 virtual int event_pending() { return _evqueue.pending(); }
435 * \param e destination where to store event information.
437 * If there is no event pending, this function blocks
438 * until there is an event to deliver.
440 virtual int get_event(Scout_gfx::Event *out_e)
447 * Screen update interface
449 virtual void *scr_adr()
450 { return _front_buffer; }
452 long ofs = _size.h() * _dbl_buffer_2 * _view_info.bytes_per_line;
453 return _fb_addr.get() + _view_info.buffer_offset + ofs;
456 virtual void scr_update(Rect const &r)
458 _view->scr_refresh(r);
462 * Exchange foreground and back buffers
466 if (_view->view_info()->has_static_buffer_offset())
468 copy_buf_to_scr(Rect(_size));
471 _dbl_buffer_2 = !_dbl_buffer_2;
472 void *tmp = _front_buffer;
473 _front_buffer = _back_buffer;
475 _view->set_buf_pos(_size.h() * (_dbl_buffer_2) * _view->view_info()->bytes_per_line);
476 _canvas->buffer(_back_buffer);
479 void copy_buf_to_scr(Rect const &r);
481 void process_redraws()
482 { _rdm.process(_view->geometry()); }
484 Scout_gfx::Parent_widget *root() { return &_ust; }
490 using L4Re::Util::cap_alloc;
491 L4Re::Env const *e = L4Re::Env::env();
492 L4::Cap<void> _mag = e->get_cap<void>("fb");
493 return _mag.is_valid();
496 Re_pf::Re_pf(Rect const &sz)
497 : Platform(), _size(sz.area()), _ready(false), _view(0),
498 _canvas(0), _dbl_buffer_2(false)
501 using L4Re::Util::cap_alloc;
504 L4Re::Video::View::Info _view_info;
506 L4Re::Env const *e = L4Re::Env::env();
507 _screen = chkcap(e->get_cap<L4Re::Console>("fb"));
508 chksys(_screen->L4Re::Video::Goos::info(&_scr_info), "requesting screen info");
510 L4Re::Video::View view;
512 if (_scr_info.has_dynamic_views())
513 chksys(_screen->create_view(&view), "creating new view");
515 view = _screen->view(0);
517 chksys(view.info(&_view_info), "requesting view infos");
519 printf("SCREEN: size = %ld, %ld, bypp=%d\n",
520 _scr_info.width, _scr_info.height,
521 _scr_info.pixel_info.bytes_per_pixel());
524 _fb_ds = cap_alloc.alloc<L4Re::Dataspace>();
526 if (!_view_info.has_static_buffer())
529 unsigned long bsize = _size.pixels() * _scr_info.pixel_info.bytes_per_pixel() * 2;
530 _view_info.buffer_index = chksys(_screen->create_buffer(bsize, _fb_ds.get()));
533 _view_info.width = sz.w();
534 _view_info.height = sz.h();
535 _view_info.buffer_offset = 0;
536 _view_info.bytes_per_line = _size.w() * _scr_info.pixel_info.bytes_per_pixel();
537 chksys(view.set_info(_view_info), "setting view infos");
541 Config::browser_attr = 7;
545 chksys(_screen->get_static_buffer(_view_info.buffer_index, _fb_ds.get()), "requesting static bvuffer");
546 _size = Area(_view_info.width, _view_info.height);
547 _back_buffer = new char[_fb_ds->size()];
552 chksys(e->rm()->attach(&_fb_addr, _fb_ds->size(), L4Re::Rm::Search_addr,
553 _fb_ds.get(), 0, L4_SUPERPAGESHIFT));
556 _view_info.dump(dbg);
557 dbg.printf(" memory %p-%p\n", (void*)_fb_addr.get(),
558 (void*)(_fb_addr.get() + _fb_ds->size()));
560 _timer.start(_screen);
564 _ust.set_geometry(Rect(Point(0,0), Area(_scr_info.width, _scr_info.height)));
565 ::Factory *f = dynamic_cast< ::Factory* >(::Factory::set.find(_view_info.pixel_info));
569 printf("No factory for this framebuffer config\n");
573 _front_buffer = _fb_addr.get() + _view_info.buffer_offset;
575 _back_buffer = _fb_addr.get() + _view_info.buffer_offset + _size.h() * _view_info.bytes_per_line;
577 _canvas = f->create_canvas(_back_buffer, scr_size(), _view_info.bytes_per_line);
580 printf("Could not create canvas\n");
584 _view = new Re_view(Rect(sz.p1(), _size), Rect(Point(0,0), scr_size()), &_rdm, _canvas, view,
585 _view_info.buffer_offset);
587 _view->set_view_info(_view_info);
589 _rdm.setup(_canvas, this, scr_size());
596 Re_pf::copy_buf_to_scr(Rect const &_r)
598 unsigned bpp = _view->view_info()->pixel_info.bytes_per_pixel();
599 Rect r = _r & Rect(scr_size());// - o;
600 /* copy background buffer to foreground buffer */
601 int len = r.w() * bpp;
602 int linelen = _view->view_info()->bytes_per_line;
604 char *src = (char*)_back_buffer + r.y1() * linelen + r.x1() * bpp;
605 char *dst = (char*)_front_buffer + r.y1() * linelen + r.x1() * bpp;
607 // blit(src, linelen, dst, linelen, len, h);
608 for (int j = 0; j < r.h(); j++, dst += linelen, src += linelen)
609 memcpy(dst, src, len);
612 static Platform::Pf_factory_t<Re_pf> pff;