/* * \brief Nitpicker-based graphics backend for scout * \date 2013-12-30 * \author Norman Feske */ /* * Copyright (C) 2013 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ #ifndef _INCLUDE__SCOUT__NITPICKER_GRAPHICS_BACKEND_H_ #define _INCLUDE__SCOUT__NITPICKER_GRAPHICS_BACKEND_H_ /* Genode includes */ #include #include #include /* Scout includes */ #include namespace Scout { using Genode::Pixel_rgb565; class Nitpicker_graphics_backend; } class Scout::Nitpicker_graphics_backend : public Graphics_backend { private: Nitpicker::Connection &_nitpicker; Genode::Dataspace_capability _init_fb_ds(Area max_size) { _nitpicker.buffer(Framebuffer::Mode(max_size.w(), max_size.h()*2, Framebuffer::Mode::RGB565), false); return _nitpicker.framebuffer()->dataspace(); } Area _max_size; Genode::Dataspace_capability _fb_ds = { _init_fb_ds(_max_size) }; void *_map_fb_ds() { return Genode::env()->rm_session()->attach(_fb_ds); } void *_fb_local_base = { _map_fb_ds() }; Point _position; Area _view_size; Nitpicker::View_client _view; Canvas_base *_canvas[2]; bool _flip_state = { false }; void _update_viewport() { _view.viewport(_position.x(), _position.y(), _view_size.w(), _view_size.h(), 0, _flip_state ? -_max_size.h() : 0, true); } void _refresh_view(Rect rect) { int const y_offset = _flip_state ? _max_size.h() : 0; _nitpicker.framebuffer()->refresh(rect.x1(), rect.y1() + y_offset, rect.w(), rect.h()); } template PT *_base(unsigned idx) { return (PT *)_fb_local_base + idx*_max_size.count(); } unsigned _front_idx() const { return _flip_state ? 1 : 0; } unsigned _back_idx() const { return _flip_state ? 0 : 1; } public: Nitpicker_graphics_backend(Nitpicker::Connection &nitpicker, Area max_size, Point position, Area view_size) : _nitpicker(nitpicker), _max_size(max_size), _position(position), _view_size(view_size), _view(_nitpicker.create_view()) { bring_to_front(); typedef Genode::Pixel_rgb565 PT; static Canvas canvas_0(_base(0), max_size); static Canvas canvas_1(_base(1), max_size); _canvas[0] = &canvas_0; _canvas[1] = &canvas_1; } /******************************** ** Graphics_backend interface ** ********************************/ Canvas_base &front() { return *_canvas[_front_idx()]; } Canvas_base &back() { return *_canvas[ _back_idx()]; } void copy_back_to_front(Rect rect) { typedef Genode::Pixel_rgb565 PT; PT const *src = _base( _back_idx()); PT *dst = _base(_front_idx()); unsigned long const offset = rect.y1()*_max_size.w() + rect.x1(); src += offset; dst += offset; blit(src, sizeof(PT)*_max_size.w(), dst, sizeof(PT)*_max_size.w(), sizeof(PT)*rect.w(), rect.h()); _refresh_view(rect); } void swap_back_and_front() { _flip_state = !_flip_state; _update_viewport(); } void position(Point p) { _position = p; _update_viewport(); } void bring_to_front() { _view.stack(Nitpicker::View_capability(), true, true); } void view_area(Area area) { _view_size = area; } }; #endif /* _INCLUDE__SCOUT__NITPICKER_GRAPHICS_BACKEND_H_ */