diff --git a/repos/dde_linux/recipes/raw/drivers_interactive-imx8q_evk/drivers.config b/repos/dde_linux/recipes/raw/drivers_interactive-imx8q_evk/drivers.config index 9ad66bb853..91f5a12e41 100644 --- a/repos/dde_linux/recipes/raw/drivers_interactive-imx8q_evk/drivers.config +++ b/repos/dde_linux/recipes/raw/drivers_interactive-imx8q_evk/drivers.config @@ -9,13 +9,11 @@ + - - - @@ -57,7 +55,6 @@ - @@ -68,6 +65,7 @@ + diff --git a/repos/dde_linux/recipes/raw/drivers_interactive-rpi/drivers.config b/repos/dde_linux/recipes/raw/drivers_interactive-rpi/drivers.config index 5bfb97e50f..3496801946 100644 --- a/repos/dde_linux/recipes/raw/drivers_interactive-rpi/drivers.config +++ b/repos/dde_linux/recipes/raw/drivers_interactive-rpi/drivers.config @@ -9,13 +9,11 @@ + - - - @@ -39,7 +37,6 @@ - @@ -49,6 +46,7 @@ + diff --git a/repos/dde_linux/recipes/src/imx8_fb_drv/used_apis b/repos/dde_linux/recipes/src/imx8_fb_drv/used_apis index da546f3ebf..da1f92e6eb 100644 --- a/repos/dde_linux/recipes/src/imx8_fb_drv/used_apis +++ b/repos/dde_linux/recipes/src/imx8_fb_drv/used_apis @@ -4,4 +4,4 @@ blit platform_session timer_session report_session -framebuffer_session +capture_session diff --git a/repos/dde_linux/recipes/src/intel_fb_drv/used_apis b/repos/dde_linux/recipes/src/intel_fb_drv/used_apis index 41904bab86..b8846965eb 100644 --- a/repos/dde_linux/recipes/src/intel_fb_drv/used_apis +++ b/repos/dde_linux/recipes/src/intel_fb_drv/used_apis @@ -3,5 +3,5 @@ os platform_session timer_session report_session -framebuffer_session +capture_session blit diff --git a/repos/dde_linux/run/intel_fb.run b/repos/dde_linux/run/intel_fb.run index 5c5ac4f581..47662238b8 100644 --- a/repos/dde_linux/run/intel_fb.run +++ b/repos/dde_linux/run/intel_fb.run @@ -128,7 +128,6 @@ append config { - @@ -149,6 +148,8 @@ append config { + + diff --git a/repos/dde_linux/src/drivers/framebuffer/imx8/include/component.h b/repos/dde_linux/src/drivers/framebuffer/imx8/include/component.h deleted file mode 100644 index 2b915a7fba..0000000000 --- a/repos/dde_linux/src/drivers/framebuffer/imx8/include/component.h +++ /dev/null @@ -1,223 +0,0 @@ -/* - * \brief i.MX8 framebuffer driver session component - * \author Stefan Kalkowski - * \author Christian Prochaska - * \date 2015-10-16 - */ - -/* - * Copyright (C) 2015-2019 Genode Labs GmbH - * - * This file is distributed under the terms of the GNU General Public License - * version 2. - */ - -#ifndef __COMPONENT_H__ -#define __COMPONENT_H__ - -/* Genode includes */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace Framebuffer { - class Driver; - class Session_component; - class Root; -} - - -class Framebuffer::Driver -{ - private: - - struct Configuration - { - struct lx_c_fb_config _lx = { 16, 64, 64, 4, - nullptr, 0, nullptr }; - } _config; - - Session_component &_session; - Timer::Connection _timer; - Genode::Reporter _reporter; - - Genode::Signal_context_capability _config_sigh; - - drm_display_mode * _preferred_mode(drm_connector *connector, - unsigned &brightness); - - public: - - Driver(Genode::Env & env, Session_component &session) - : _session(session), _timer(env), - _reporter(env, "connectors") {} - - int width() const { return _config._lx.width; } - int height() const { return _config._lx.height; } - int bpp() const { return _config._lx.bpp; } - - void * fb_addr() const { return _config._lx.addr; } - unsigned pitch() const { return _config._lx.pitch; } - - void finish_initialization(); - - void update_mode(); - - void generate_report(); - - /** - * Register signal handler used for config updates - * - * The signal handler is artificially triggered as a side effect - * of connector changes. - */ - void config_sigh(Genode::Signal_context_capability sigh) - { - _config_sigh = sigh; - } - - void trigger_reconfiguration() - { - /* - * Trigger the reprocessing of the configuration following the - * same ontrol flow as used for external config changes. - */ - if (_config_sigh.valid()) - Genode::Signal_transmitter(_config_sigh).submit(); - else - Genode::warning("config signal handler unexpectedly undefined"); - } -}; - - -class Framebuffer::Session_component : public Genode::Rpc_object -{ - private: - - template using Lazy = Genode::Constructible; - - Driver _driver; - Genode::Attached_rom_dataspace &_config; - Genode::Signal_context_capability _mode_sigh; - Timer::Connection _timer; - Genode::Ram_allocator &_ram; - Genode::Attached_ram_dataspace _ds; - bool _in_mode_change = true; - - public: - - Session_component(Genode::Env &env, - Genode::Attached_rom_dataspace &config) - : _driver(env, *this), _config(config), _timer(env), - _ram(env.ram()), _ds(env.ram(), env.rm(), 0) {} - - Driver & driver() { return _driver; } - - void config_changed() - { - _config.update(); - if (!_config.valid()) return; - - _in_mode_change = true; - - _driver.update_mode(); - - if (_mode_sigh.valid()) - Genode::Signal_transmitter(_mode_sigh).submit(); - } - - Genode::Xml_node config() { return _config.xml(); } - - int force_width_from_config() - { - return _config.xml().attribute_value("force_width", 0); - } - - int force_height_from_config() - { - return _config.xml().attribute_value("force_height", 0); - } - - /*********************************** - ** Framebuffer session interface ** - ***********************************/ - - Genode::Dataspace_capability dataspace() override - { - _ds.realloc(&_ram, _driver.width() * _driver.height() * - mode().bytes_per_pixel()); - _in_mode_change = false; - return _ds.cap(); - } - - Mode mode() const override { - return Mode { .area = { _driver.width(), _driver.height() } }; } - - void mode_sigh(Genode::Signal_context_capability sigh) override { - _mode_sigh = sigh; } - - void sync_sigh(Genode::Signal_context_capability sigh) override - { - _timer.sigh(sigh); - _timer.trigger_periodic(10*1000); - } - - void refresh(int x, int y, int w, int h) override - { - using namespace Genode; - - if (!_driver.fb_addr() || !_ds.local_addr() || _in_mode_change) - return; - - int width = _driver.width(); - int height = _driver.height(); - unsigned bpp = 4; - unsigned pitch = _driver.width(); - - /* clip specified coordinates against screen boundaries */ - int x2 = min(x + w - 1, width - 1), - y2 = min(y + h - 1, height - 1); - int x1 = max(x, 0), - y1 = max(y, 0); - if (x1 > x2 || y1 > y2) return; - - /* copy pixels from back buffer to physical frame buffer */ - char *src = _ds.local_addr() + bpp*(width*y1 + x1), - *dst = (char*)_driver.fb_addr() + bpp*(pitch*y1 + x1); - - blit(src, bpp*width, dst, bpp*pitch, - bpp*(x2 - x1 + 1), y2 - y1 + 1); - } -}; - - -struct Framebuffer::Root -: Genode::Root_component -{ - Session_component session; /* single session */ - - Session_component *_create_session(const char *) override { - return &session; } - - void _destroy_session(Session_component *) override { } - - Root(Genode::Env &env, Genode::Allocator &alloc, - Genode::Attached_rom_dataspace &config) - : Genode::Root_component(env.ep(), alloc), - session(env, config) { } -}; - -#endif /* __COMPONENT_H__ */ diff --git a/repos/dde_linux/src/drivers/framebuffer/imx8/include/driver.h b/repos/dde_linux/src/drivers/framebuffer/imx8/include/driver.h new file mode 100644 index 0000000000..095d950ce4 --- /dev/null +++ b/repos/dde_linux/src/drivers/framebuffer/imx8/include/driver.h @@ -0,0 +1,156 @@ +/* + * \brief i.MX8 framebuffer driver + * \author Stefan Kalkowski + * \author Norman Feske + * \author Christian Prochaska + * \date 2015-10-16 + */ + +/* + * Copyright (C) 2015-2020 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef __DRIVER_H__ +#define __DRIVER_H__ + +/* Genode includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace Framebuffer { + + using namespace Genode; + class Driver; +} + + +class Framebuffer::Driver +{ + private: + + using Area = Capture::Area; + using Pixel = Capture::Pixel; + + struct Configuration + { + struct lx_c_fb_config _lx = { .height = 16, + .width = 64, + .pitch = 64, + .bpp = 4, + .addr = nullptr, + .size = 0, + .lx_fb = nullptr }; + } _lx_config; + + Env &_env; + + Attached_rom_dataspace &_config; + + Timer::Connection _timer { _env }; + + Reporter _reporter { _env, "connectors" }; + + Signal_context_capability _config_sigh; + + drm_display_mode * _preferred_mode(drm_connector *connector, + unsigned &brightness); + + /* + * Capture + */ + + Capture::Connection _capture { _env }; + + Constructible _captured_screen { }; + + Timer::Connection _capture_timer { _env }; + + Signal_handler _capture_timer_handler { + _env.ep(), *this, &Driver::_handle_capture_timer }; + + void _handle_capture_timer() + { + if (!_captured_screen.constructed()) + return; + + Area const phys_size { _lx_config._lx.pitch/sizeof(Pixel), + _lx_config._lx.height }; + + Capture::Surface surface((Pixel *)_lx_config._lx.addr, phys_size); + + _captured_screen->apply_to_surface(surface); + } + + int _force_width_from_config() + { + return _config.xml().attribute_value("force_width", 0); + } + + int _force_height_from_config() + { + return _config.xml().attribute_value("force_height", 0); + } + + public: + + Driver(Env &env, Attached_rom_dataspace &config) + : + _env(env), _config(config) + { + _capture_timer.sigh(_capture_timer_handler); + } + + void finish_initialization(); + void update_mode(); + void generate_report(); + + /** + * Register signal handler used for config updates + * + * The signal handler is artificially triggered as a side effect + * of connector changes. + */ + void config_sigh(Signal_context_capability sigh) + { + _config_sigh = sigh; + } + + void trigger_reconfiguration() + { + /* + * Trigger the reprocessing of the configuration following the + * same ontrol flow as used for external config changes. + */ + if (_config_sigh.valid()) + Signal_transmitter(_config_sigh).submit(); + else + warning("config signal handler unexpectedly undefined"); + } + + void config_changed() + { + _config.update(); + + update_mode(); + + Area const size { _lx_config._lx.width, _lx_config._lx.height }; + + _captured_screen.construct(_capture, _env.rm(), size); + + _capture_timer.trigger_periodic(10*1000); + } +}; + +#endif /* __DRIVER_H__ */ diff --git a/repos/dde_linux/src/drivers/framebuffer/imx8/lx_emul.cc b/repos/dde_linux/src/drivers/framebuffer/imx8/lx_emul.cc index b75e8136cd..f9facbde94 100644 --- a/repos/dde_linux/src/drivers/framebuffer/imx8/lx_emul.cc +++ b/repos/dde_linux/src/drivers/framebuffer/imx8/lx_emul.cc @@ -17,7 +17,7 @@ #include /* local includes */ -#include +#include #include #include @@ -1053,7 +1053,7 @@ Framebuffer::Driver::_preferred_mode(drm_connector *connector, /* try to read configuration for connector */ try { - Xml_node config = _session.config(); + Xml_node config = _config.xml(); Xml_node xn = config.sub_node(); for (unsigned i = 0; i < config.num_sub_nodes(); xn = xn.next()) { if (!xn.has_type("connector")) @@ -1114,7 +1114,7 @@ void Framebuffer::Driver::finish_initialization() generate_report(); - _session.config_changed(); + config_changed(); } @@ -1122,21 +1122,21 @@ void Framebuffer::Driver::update_mode() { using namespace Genode; - Configuration old = _config; - _config = Configuration(); + Configuration old = _lx_config; + _lx_config = Configuration(); lx_for_each_connector(lx_drm_device, [&] (drm_connector *c) { unsigned brightness; drm_display_mode * mode = _preferred_mode(c, brightness); if (!mode) return; - if (mode->hdisplay > _config._lx.width) _config._lx.width = mode->hdisplay; - if (mode->vdisplay > _config._lx.height) _config._lx.height = mode->vdisplay; + if (mode->hdisplay > _lx_config._lx.width) _lx_config._lx.width = mode->hdisplay; + if (mode->vdisplay > _lx_config._lx.height) _lx_config._lx.height = mode->vdisplay; }); - lx_c_allocate_framebuffer(lx_drm_device, &_config._lx); + lx_c_allocate_framebuffer(lx_drm_device, &_lx_config._lx); - if (!_config._lx.lx_fb) { + if (!_lx_config._lx.lx_fb) { Genode::error("updating framebuffer failed"); return; } @@ -1147,16 +1147,16 @@ void Framebuffer::Driver::update_mode() unsigned brightness = MAX_BRIGHTNESS + 1; /* set mode */ - lx_c_set_mode(lx_drm_device, c, _config._lx.lx_fb, + lx_c_set_mode(lx_drm_device, c, _lx_config._lx.lx_fb, _preferred_mode(c, brightness)); }); } /* force virtual framebuffer size if requested */ - if (int w = _session.force_width_from_config()) - _config._lx.width = min(_config._lx.width, w); - if (int h = _session.force_height_from_config()) - _config._lx.height = min(_config._lx.height, h); + if (int w = _force_width_from_config()) + _lx_config._lx.width = min(_lx_config._lx.width, w); + if (int h = _force_height_from_config()) + _lx_config._lx.height = min(_lx_config._lx.height, h); if (old._lx.lx_fb) { if (drm_framebuffer_read_refcount(old._lx.lx_fb) > 1) { @@ -1197,8 +1197,8 @@ void Framebuffer::Driver::generate_report() /* check for report configuration option */ try { - _reporter.enabled(_session.config().sub_node("report") - .attribute_value(_reporter.name().string(), false)); + _reporter.enabled(_config.xml().sub_node("report") + .attribute_value(_reporter.name().string(), false)); } catch (...) { _reporter.enabled(false); } diff --git a/repos/dde_linux/src/drivers/framebuffer/imx8/main.cc b/repos/dde_linux/src/drivers/framebuffer/imx8/main.cc index 1d4b8b15a3..690b67fa1b 100644 --- a/repos/dde_linux/src/drivers/framebuffer/imx8/main.cc +++ b/repos/dde_linux/src/drivers/framebuffer/imx8/main.cc @@ -7,7 +7,7 @@ */ /* - * Copyright (C) 2015-2019 Genode Labs GmbH + * Copyright (C) 2015-2020 Genode Labs GmbH * * This file is distributed under the terms of the GNU General Public License * version 2. @@ -19,8 +19,8 @@ #include #include -/* Server related local includes */ -#include +/* local includes */ +#include /* Linux emulation environment includes */ #include @@ -32,7 +32,7 @@ #include /* Linux module functions */ -extern "C" void radix_tree_init(); /* called by start_kernel(void) normally */ +extern "C" void radix_tree_init(); /* called by start_kernel(void) normally */ extern "C" void drm_connector_ida_init(); /* called by drm_core_init(void) normally */ extern "C" int module_irq_imx_irqsteer_init(); extern "C" int module_imx_drm_pdrv_init(); @@ -40,90 +40,79 @@ extern "C" int module_dcss_driver_init(); extern "C" int module_dcss_crtc_driver_init(); extern "C" int module_imx_hdp_imx_platform_driver_init(); - -static void run_linux(void * m); - unsigned long jiffies; +namespace Framebuffer { struct Main; } -struct Main + +struct Framebuffer::Main { - Genode::Env &env; - Genode::Entrypoint &ep { env.ep() }; - Genode::Attached_rom_dataspace config { env, "config" }; - Genode::Heap heap { env.ram(), env.rm() }; - Framebuffer::Root root { env, heap, config }; + void _run_linux(); + /** + * Entry for executing code in the Linux kernel context + */ + static void _run_linux_entry(void *m) + { + reinterpret_cast(m)->_run_linux(); + } + + Env &_env; + Entrypoint &_ep { _env.ep() }; + Attached_rom_dataspace _config { _env, "config" }; + Heap _heap { _env.ram(), _env.rm() }; + Driver _driver { _env, _config }; /* Linux task that handles the initialization */ - Genode::Constructible linux; + Constructible _linux; - Main(Genode::Env &env) : env(env) + Signal_handler
_policy_change_handler { + _env.ep(), *this, &Main::_handle_policy_change }; + + bool _policy_change_pending = false; + + void _handle_policy_change() { - Genode::log("--- i.MX8 framebuffer driver ---"); + _policy_change_pending = true; + _linux->unblock(); + Lx::scheduler().schedule(); + } - Lx_kit::construct_env(env); + Main(Env &env) : _env(env) + { + log("--- i.MX8 framebuffer driver ---"); + + Lx_kit::construct_env(_env); LX_MUTEX_INIT(bridge_lock); LX_MUTEX_INIT(core_lock); LX_MUTEX_INIT(component_mutex); /* init singleton Lx::Scheduler */ - Lx::scheduler(&env); + Lx::scheduler(&_env); - Lx::malloc_init(env, heap); + Lx::malloc_init(_env, _heap); /* init singleton Lx::Timer */ - Lx::timer(&env, &ep, &heap, &jiffies); + Lx::timer(&_env, &_ep, &_heap, &jiffies); /* init singleton Lx::Irq */ - Lx::Irq::irq(&ep, &heap); + Lx::Irq::irq(&_ep, &_heap); /* init singleton Lx::Work */ - Lx::Work::work_queue(&heap); + Lx::Work::work_queue(&_heap); - linux.construct(run_linux, reinterpret_cast(this), - "linux", Lx::Task::PRIORITY_0, Lx::scheduler()); + _linux.construct(_run_linux_entry, reinterpret_cast(this), + "linux", Lx::Task::PRIORITY_0, Lx::scheduler()); /* give all task a first kick before returning */ Lx::scheduler().schedule(); } - - void announce() { env.parent().announce(ep.manage(root)); } - - Lx::Task &linux_task() { return *linux; } }; -struct Policy_agent +void Framebuffer::Main::_run_linux() { - Main &main; - Genode::Signal_handler handler; - bool _pending = false; - - void handle() - { - _pending = true; - main.linux_task().unblock(); - Lx::scheduler().schedule(); - } - - bool pending() - { - bool ret = _pending; - _pending = false; - return ret; - } - - Policy_agent(Main &m) - : main(m), handler(main.ep, *this, &Policy_agent::handle) {} -}; - - -static void run_linux(void * m) -{ - Main * main = reinterpret_cast(m); - system_wq = alloc_workqueue("system_wq", 0, 0); radix_tree_init(); @@ -240,17 +229,17 @@ static void run_linux(void * m) platform_device_register(display_subsystem_pdev); - main->root.session.driver().finish_initialization(); - main->announce(); + _driver.finish_initialization(); + _driver.config_sigh(_policy_change_handler); - Policy_agent pa(*main); - main->root.session.driver().config_sigh(pa.handler); - main->config.sigh(pa.handler); + _config.sigh(_policy_change_handler); while (1) { Lx::scheduler().current()->block_and_schedule(); - while (pa.pending()) - main->root.session.config_changed(); + while (_policy_change_pending) { + _policy_change_pending = false; + _driver.config_changed(); + } } } @@ -260,5 +249,5 @@ void Component::construct(Genode::Env &env) /* XXX execute constructors of global statics */ env.exec_static_constructors(); - static Main m(env); + static Framebuffer::Main main(env); } diff --git a/repos/dde_linux/src/drivers/framebuffer/intel/include/component.h b/repos/dde_linux/src/drivers/framebuffer/intel/include/component.h deleted file mode 100644 index dfa47e2a5c..0000000000 --- a/repos/dde_linux/src/drivers/framebuffer/intel/include/component.h +++ /dev/null @@ -1,237 +0,0 @@ -/* - * \brief Intel framebuffer driver session component - * \author Stefan Kalkowski - * \date 2015-10-16 - */ - -/* - * Copyright (C) 2015-2017 Genode Labs GmbH - * - * This file is distributed under the terms of the GNU General Public License - * version 2. - */ - -#ifndef __COMPONENT_H__ -#define __COMPONENT_H__ - -/* Genode includes */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace Framebuffer { - class Driver; - class Session_component; - class Root; -} - - -class Framebuffer::Driver -{ - private: - - struct Configuration - { - struct lx_c_fb_config _lx = { .height = 16, - .width = 64, - .pitch = 64, - .bpp = 4, - .addr = nullptr, - .size = 0, - .lx_fb = nullptr }; - } _config; - - Session_component &_session; - Timer::Connection _timer; - Genode::Reporter _reporter; - Genode::Signal_handler _poll_handler; - Genode::uint64_t _poll_ms = 0; - - Genode::Signal_context_capability _config_sigh; - - drm_display_mode * _preferred_mode(drm_connector *connector, - unsigned &brightness); - - void _poll(); - - public: - - Driver(Genode::Env & env, Session_component &session) - : _session(session), _timer(env), - _reporter(env, "connectors"), - _poll_handler(env.ep(), *this, &Driver::_poll) {} - - int width() const { return _config._lx.width; } - int height() const { return _config._lx.height; } - int bpp() const { return _config._lx.bpp; } - void * fb_addr() const { return _config._lx.addr; } - unsigned pitch() const { return _config._lx.pitch; } - - void finish_initialization(); - void set_polling(Genode::uint64_t poll); - void update_mode(); - void generate_report(); - - /** - * Register signal handler used for config updates - * - * The signal handler is artificially triggered as a side effect - * of connector changes. - */ - void config_sigh(Genode::Signal_context_capability sigh) - { - _config_sigh = sigh; - } - - void trigger_reconfiguration() - { - /* - * Trigger the reprocessing of the configuration following the - * same ontrol flow as used for external config changes. - */ - if (_config_sigh.valid()) - Genode::Signal_transmitter(_config_sigh).submit(); - else - Genode::warning("config signal handler unexpectedly undefined"); - } -}; - - -class Framebuffer::Session_component : public Genode::Rpc_object -{ - private: - - template using Lazy = Genode::Constructible; - - Driver _driver; - Genode::Attached_rom_dataspace &_config; - Genode::Signal_context_capability _mode_sigh; - Timer::Connection _timer; - Genode::Ram_allocator &_ram; - Genode::Attached_ram_dataspace _ds; - bool _in_mode_change = true; - - Genode::uint64_t _polling_from_config() { - return _config.xml().attribute_value("poll", 0); } - - public: - - Session_component(Genode::Env &env, - Genode::Attached_rom_dataspace &config) - : _driver(env, *this), _config(config), _timer(env), - _ram(env.ram()), _ds(env.ram(), env.rm(), 0) {} - - Driver & driver() { return _driver; } - - void config_changed() - { - _config.update(); - if (!_config.valid()) return; - - _driver.set_polling(_polling_from_config()); - - _in_mode_change = true; - - _driver.update_mode(); - - if (_mode_sigh.valid()) - Genode::Signal_transmitter(_mode_sigh).submit(); - } - - Genode::Xml_node config() { return _config.xml(); } - - int force_width_from_config() - { - return _config.xml().attribute_value("force_width", 0); - } - - int force_height_from_config() - { - return _config.xml().attribute_value("force_height", 0); - } - - - /*********************************** - ** Framebuffer session interface ** - ***********************************/ - - Genode::Dataspace_capability dataspace() override - { - _ds.realloc(&_ram, _driver.width()*_driver.height()*_driver.bpp()); - _in_mode_change = false; - return _ds.cap(); - } - - Mode mode() const override - { - return Mode { .area { _driver.width(), _driver.height() } }; - } - - void mode_sigh(Genode::Signal_context_capability sigh) override { - _mode_sigh = sigh; } - - void sync_sigh(Genode::Signal_context_capability sigh) override - { - _timer.sigh(sigh); - _timer.trigger_periodic(10*1000); - } - - void refresh(int x, int y, int w, int h) override - { - using namespace Genode; - - if (!_driver.fb_addr() || - !_ds.local_addr() || - _in_mode_change) return; - - int width = _driver.width(); - int height = _driver.height(); - unsigned bpp = _driver.bpp(); - unsigned pitch = _driver.pitch(); - - /* clip specified coordinates against screen boundaries */ - int x2 = min(x + w - 1, width - 1), - y2 = min(y + h - 1, height - 1); - int x1 = max(x, 0), - y1 = max(y, 0); - if (x1 > x2 || y1 > y2) return; - - /* copy pixels from back buffer to physical frame buffer */ - char *src = _ds.local_addr() + bpp*(width*y1 + x1), - *dst = (char*)_driver.fb_addr() + pitch*y1 + bpp*x1; - - blit(src, bpp*width, dst, pitch, - bpp*(x2 - x1 + 1), y2 - y1 + 1); - } -}; - - -struct Framebuffer::Root -: Genode::Root_component -{ - Session_component session; /* single session */ - - Session_component *_create_session(const char *) override { - return &session; } - - void _destroy_session(Session_component *) override { } - - Root(Genode::Env &env, Genode::Allocator &alloc, - Genode::Attached_rom_dataspace &config) - : Genode::Root_component(env.ep(), alloc), - session(env, config) { } -}; - -#endif /* __COMPONENT_H__ */ diff --git a/repos/dde_linux/src/drivers/framebuffer/intel/include/driver.h b/repos/dde_linux/src/drivers/framebuffer/intel/include/driver.h new file mode 100644 index 0000000000..797877cc20 --- /dev/null +++ b/repos/dde_linux/src/drivers/framebuffer/intel/include/driver.h @@ -0,0 +1,168 @@ +/* + * \brief Intel framebuffer driver + * \author Stefan Kalkowski + * \author Norman Feske + * \date 2015-10-16 + */ + +/* + * Copyright (C) 2015-2020 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef __DRIVER_H__ +#define __DRIVER_H__ + +/* Genode includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace Framebuffer { + + using namespace Genode; + class Driver; +} + + +class Framebuffer::Driver +{ + private: + + using Area = Capture::Area; + using Pixel = Capture::Pixel; + + struct Configuration + { + struct lx_c_fb_config _lx = { .height = 16, + .width = 64, + .pitch = 64, + .bpp = 4, + .addr = nullptr, + .size = 0, + .lx_fb = nullptr }; + } _lx_config; + + Env &_env; + + Attached_rom_dataspace &_config; + + Timer::Connection _timer { _env }; + + Reporter _reporter { _env, "connectors" }; + + Signal_handler _poll_handler { _env.ep(), *this, &Driver::_poll }; + + uint64_t _poll_ms = 0; + + Signal_context_capability _config_sigh; + + drm_display_mode * _preferred_mode(drm_connector *connector, + unsigned &brightness); + + void _poll(); + + uint64_t _polling_from_config() { + return _config.xml().attribute_value("poll", 0); } + + + /* + * Capture + */ + + Capture::Connection _capture { _env }; + + Constructible _captured_screen { }; + + Timer::Connection _capture_timer { _env }; + + Signal_handler _capture_timer_handler { + _env.ep(), *this, &Driver::_handle_capture_timer }; + + void _handle_capture_timer() + { + if (!_captured_screen.constructed()) + return; + + Area const phys_size { _lx_config._lx.pitch/sizeof(Pixel), + _lx_config._lx.height }; + + Capture::Surface surface((Pixel *)_lx_config._lx.addr, phys_size); + + _captured_screen->apply_to_surface(surface); + } + + int _force_width_from_config() + { + return _config.xml().attribute_value("force_width", 0); + } + + int _force_height_from_config() + { + return _config.xml().attribute_value("force_height", 0); + } + + public: + + Driver(Env &env, Attached_rom_dataspace &config) + : + _env(env), _config(config) + { + _capture_timer.sigh(_capture_timer_handler); + } + + void finish_initialization(); + void set_polling(uint64_t poll); + void update_mode(); + void generate_report(); + + /** + * Register signal handler used for config updates + * + * The signal handler is artificially triggered as a side effect + * of connector changes. + */ + void config_sigh(Signal_context_capability sigh) + { + _config_sigh = sigh; + } + + void trigger_reconfiguration() + { + /* + * Trigger the reprocessing of the configuration following the + * same ontrol flow as used for external config changes. + */ + if (_config_sigh.valid()) + Signal_transmitter(_config_sigh).submit(); + else + warning("config signal handler unexpectedly undefined"); + } + + void config_changed() + { + _config.update(); + + set_polling(_polling_from_config()); + + update_mode(); + + Area const size { _lx_config._lx.width, _lx_config._lx.height }; + + _captured_screen.construct(_capture, _env.rm(), size); + + _capture_timer.trigger_periodic(10*1000); + } +}; + +#endif /* __DRIVER_H__ */ diff --git a/repos/dde_linux/src/drivers/framebuffer/intel/lx_emul.cc b/repos/dde_linux/src/drivers/framebuffer/intel/lx_emul.cc index 50c3ae4484..823d9f44ab 100644 --- a/repos/dde_linux/src/drivers/framebuffer/intel/lx_emul.cc +++ b/repos/dde_linux/src/drivers/framebuffer/intel/lx_emul.cc @@ -19,7 +19,7 @@ #include /* local includes */ -#include +#include /* DRM-specific includes */ #include @@ -100,7 +100,7 @@ Framebuffer::Driver::_preferred_mode(drm_connector *connector, /* try to read configuration for connector */ try { - Xml_node config = _session.config(); + Xml_node config = _config.xml(); Xml_node xn = config.sub_node(); for (unsigned i = 0; i < config.num_sub_nodes(); xn = xn.next()) { if (!xn.has_type("connector")) @@ -157,7 +157,7 @@ void Framebuffer::Driver::finish_initialization() lx_c_set_driver(lx_drm_device, (void*)this); generate_report(); - _session.config_changed(); + Driver::config_changed(); } @@ -189,20 +189,20 @@ void Framebuffer::Driver::update_mode() { using namespace Genode; - Configuration old = _config; - _config = Configuration(); + Configuration old = _lx_config; + _lx_config = Configuration(); lx_for_each_connector(lx_drm_device, [&] (drm_connector *c) { unsigned brightness; drm_display_mode * mode = _preferred_mode(c, brightness); if (!mode) return; - if (mode->hdisplay > _config._lx.width) _config._lx.width = mode->hdisplay; - if (mode->vdisplay > _config._lx.height) _config._lx.height = mode->vdisplay; + if (mode->hdisplay > _lx_config._lx.width) _lx_config._lx.width = mode->hdisplay; + if (mode->vdisplay > _lx_config._lx.height) _lx_config._lx.height = mode->vdisplay; }); - lx_c_allocate_framebuffer(lx_drm_device, &_config._lx); + lx_c_allocate_framebuffer(lx_drm_device, &_lx_config._lx); - if (!_config._lx.lx_fb) { + if (!_lx_config._lx.lx_fb) { Genode::error("updating framebuffer failed"); return; } @@ -213,7 +213,7 @@ void Framebuffer::Driver::update_mode() unsigned brightness = MAX_BRIGHTNESS + 1; /* set mode */ - lx_c_set_mode(lx_drm_device, c, _config._lx.lx_fb, + lx_c_set_mode(lx_drm_device, c, _lx_config._lx.lx_fb, _preferred_mode(c, brightness)); /* set sane brightness, ignore unsane values and let as is */ @@ -223,10 +223,10 @@ void Framebuffer::Driver::update_mode() } /* force virtual framebuffer size if requested */ - if (int w = _session.force_width_from_config()) - _config._lx.width = min(_config._lx.width, w); - if (int h = _session.force_height_from_config()) - _config._lx.height = min(_config._lx.height, h); + if (int w = _force_width_from_config()) + _lx_config._lx.width = min(_lx_config._lx.width, w); + if (int h = _force_height_from_config()) + _lx_config._lx.height = min(_lx_config._lx.height, h); if (old._lx.addr) Lx::iounmap(old._lx.addr); if (old._lx.lx_fb) { @@ -268,7 +268,7 @@ void Framebuffer::Driver::generate_report() /* check for report configuration option */ try { - _reporter.enabled(_session.config().sub_node("report") + _reporter.enabled(_config.xml().sub_node("report") .attribute_value(_reporter.name().string(), false)); } catch (...) { _reporter.enabled(false); diff --git a/repos/dde_linux/src/drivers/framebuffer/intel/main.cc b/repos/dde_linux/src/drivers/framebuffer/intel/main.cc index 352055d9ee..7d64d7ac62 100644 --- a/repos/dde_linux/src/drivers/framebuffer/intel/main.cc +++ b/repos/dde_linux/src/drivers/framebuffer/intel/main.cc @@ -6,7 +6,7 @@ */ /* - * Copyright (C) 2015-2017 Genode Labs GmbH + * Copyright (C) 2015-2020 Genode Labs GmbH * * This file is distributed under the terms of the GNU General Public License * version 2. @@ -18,8 +18,8 @@ #include #include -/* Server related local includes */ -#include +/* local includes */ +#include /* Linux emulation environment includes */ #include @@ -33,110 +33,102 @@ #include /* Linux module functions */ -extern "C" void postcore_i2c_init(void); /* i2c-core-base.c */ -extern "C" int module_i915_init(); /* i915_drv.c */ -extern "C" void radix_tree_init(); /* called by start_kernel(void) normally */ +extern "C" void postcore_i2c_init(void); /* i2c-core-base.c */ +extern "C" int module_i915_init(); /* i915_drv.c */ +extern "C" void radix_tree_init(); /* called by start_kernel(void) normally */ extern "C" void drm_connector_ida_init(); /* called by drm_core_init(void) normally */ -static void run_linux(void * m); - unsigned long jiffies; +namespace Framebuffer { struct Main; } -struct Main + +struct Framebuffer::Main { - Genode::Env &env; - Genode::Entrypoint &ep { env.ep() }; - Genode::Attached_rom_dataspace config { env, "config" }; - Genode::Heap heap { env.ram(), env.rm() }; - Framebuffer::Root root { env, heap, config }; + void _run_linux(); + + /** + * Entry for executing code in the Linux kernel context + */ + static void _run_linux_entry(void *m) + { + reinterpret_cast(m)->_run_linux(); + } + + Env &_env; + Entrypoint &_ep { _env.ep() }; + Attached_rom_dataspace _config { _env, "config" }; + Heap _heap { _env.ram(), _env.rm() }; + Driver _driver { _env, _config }; /* Linux task that handles the initialization */ - Genode::Constructible linux; + Constructible _linux; - Main(Genode::Env &env) : env(env) + Signal_handler
_policy_change_handler { + _env.ep(), *this, &Main::_handle_policy_change }; + + bool _policy_change_pending = false; + + void _handle_policy_change() { - Genode::log("--- intel framebuffer driver ---"); + _policy_change_pending = true; + _linux->unblock(); + Lx::scheduler().schedule(); + } - Lx_kit::construct_env(env); + Main(Env &env) : _env(env) + { + log("--- intel framebuffer driver ---"); + + Lx_kit::construct_env(_env); LX_MUTEX_INIT(bridge_lock); LX_MUTEX_INIT(core_lock); /* init singleton Lx::Scheduler */ - Lx::scheduler(&env); + Lx::scheduler(&_env); - Lx::pci_init(env, env.ram(), heap); - Lx::malloc_init(env, heap); + Lx::pci_init(_env, _env.ram(), _heap); + Lx::malloc_init(_env, _heap); /* init singleton Lx::Timer */ - Lx::timer(&env, &ep, &heap, &jiffies); + Lx::timer(&_env, &_ep, &_heap, &jiffies); /* init singleton Lx::Irq */ - Lx::Irq::irq(&ep, &heap); + Lx::Irq::irq(&_ep, &_heap); /* init singleton Lx::Work */ - Lx::Work::work_queue(&heap); + Lx::Work::work_queue(&_heap); - linux.construct(run_linux, reinterpret_cast(this), - "linux", Lx::Task::PRIORITY_0, Lx::scheduler()); + _linux.construct(_run_linux_entry, reinterpret_cast(this), + "linux", Lx::Task::PRIORITY_0, Lx::scheduler()); /* give all task a first kick before returning */ Lx::scheduler().schedule(); } - - void announce() { env.parent().announce(ep.manage(root)); } - - Lx::Task &linux_task() { return *linux; } }; -struct Policy_agent +void Framebuffer::Main::_run_linux() { - Main &main; - Genode::Signal_handler handler; - bool _pending = false; - - void handle() - { - _pending = true; - main.linux_task().unblock(); - Lx::scheduler().schedule(); - } - - bool pending() - { - bool ret = _pending; - _pending = false; - return ret; - } - - Policy_agent(Main &m) - : main(m), handler(main.ep, *this, &Policy_agent::handle) {} -}; - - -static void run_linux(void * m) -{ - Main * main = reinterpret_cast(m); - system_wq = alloc_workqueue("system_wq", 0, 0); radix_tree_init(); drm_connector_ida_init(); postcore_i2c_init(); module_i915_init(); - main->root.session.driver().finish_initialization(); - main->announce(); - Policy_agent pa(*main); - main->root.session.driver().config_sigh(pa.handler); - main->config.sigh(pa.handler); + _driver.finish_initialization(); + _driver.config_sigh(_policy_change_handler); + + _config.sigh(_policy_change_handler); while (1) { Lx::scheduler().current()->block_and_schedule(); - while (pa.pending()) - main->root.session.config_changed(); + while (_policy_change_pending) { + _policy_change_pending = false; + _driver.config_changed(); + } } } @@ -146,5 +138,5 @@ void Component::construct(Genode::Env &env) /* XXX execute constructors of global statics */ env.exec_static_constructors(); - static Main m(env); + static Framebuffer::Main main(env); } diff --git a/repos/gems/recipes/raw/drivers_managed-pc/drivers.config b/repos/gems/recipes/raw/drivers_managed-pc/drivers.config index 8492f6f5fd..b1583d20f0 100644 --- a/repos/gems/recipes/raw/drivers_managed-pc/drivers.config +++ b/repos/gems/recipes/raw/drivers_managed-pc/drivers.config @@ -11,6 +11,7 @@ + @@ -19,9 +20,6 @@ - - - @@ -228,6 +226,7 @@ + diff --git a/repos/gems/recipes/src/driver_manager/used_apis b/repos/gems/recipes/src/driver_manager/used_apis index 285587958c..8f0c8889ba 100644 --- a/repos/gems/recipes/src/driver_manager/used_apis +++ b/repos/gems/recipes/src/driver_manager/used_apis @@ -3,6 +3,6 @@ os report_session block_session usb_session -framebuffer_session +capture_session timer_session platform_session diff --git a/repos/gems/run/cpu_load_display.run b/repos/gems/run/cpu_load_display.run index cfb9a166fe..08c9640abd 100644 --- a/repos/gems/run/cpu_load_display.run +++ b/repos/gems/run/cpu_load_display.run @@ -37,18 +37,19 @@ install_config { - + + - - - + - - + + + + diff --git a/repos/gems/run/decorator.run b/repos/gems/run/decorator.run index 61963ad91b..ac17cfcf08 100644 --- a/repos/gems/run/decorator.run +++ b/repos/gems/run/decorator.run @@ -39,12 +39,11 @@ install_config { - + + - - - + @@ -58,8 +57,9 @@ install_config { - - + + + @@ -168,6 +168,7 @@ install_config { + } diff --git a/repos/gems/run/decorator_stress.run b/repos/gems/run/decorator_stress.run index 3766c9b94b..b10ba7a333 100644 --- a/repos/gems/run/decorator_stress.run +++ b/repos/gems/run/decorator_stress.run @@ -41,18 +41,18 @@ install_config { - + + - - - + - - + + + diff --git a/repos/gems/run/depot_deploy.run b/repos/gems/run/depot_deploy.run index c6c1000820..d51a24b19f 100644 --- a/repos/gems/run/depot_deploy.run +++ b/repos/gems/run/depot_deploy.run @@ -50,18 +50,18 @@ install_config { - + + - - - + - - + + + diff --git a/repos/gems/run/driver_manager.run b/repos/gems/run/driver_manager.run index b7b7aa9275..e50c5ac062 100644 --- a/repos/gems/run/driver_manager.run +++ b/repos/gems/run/driver_manager.run @@ -11,6 +11,7 @@ import_from_depot [depot_user]/src/[base_src] \ [depot_user]/pkg/drivers_managed-pc \ [depot_user]/src/report_rom \ [depot_user]/src/dynamic_rom \ + [depot_user]/src/nitpicker \ [depot_user]/src/init install_config { @@ -41,6 +42,7 @@ install_config { + @@ -57,13 +59,13 @@ install_config { - - + + + - @@ -95,16 +97,30 @@ install_config { + + + + + + + + + + + + + - + + diff --git a/repos/gems/run/gui_fader.run b/repos/gems/run/gui_fader.run index 4121ce88d3..915e8bc2ad 100644 --- a/repos/gems/run/gui_fader.run +++ b/repos/gems/run/gui_fader.run @@ -36,18 +36,19 @@ install_config { - + + - - - + - - + + + + diff --git a/repos/gems/run/leitzentrale.run b/repos/gems/run/leitzentrale.run index 7c2a48014f..bba1ae0360 100644 --- a/repos/gems/run/leitzentrale.run +++ b/repos/gems/run/leitzentrale.run @@ -70,12 +70,11 @@ install_config { - + + - - - + @@ -93,8 +92,9 @@ install_config { - - + + + @@ -226,7 +226,7 @@ install_config { - + diff --git a/repos/gems/run/menu_view.run b/repos/gems/run/menu_view.run index dad398b284..b8afc0cd3d 100644 --- a/repos/gems/run/menu_view.run +++ b/repos/gems/run/menu_view.run @@ -40,18 +40,19 @@ install_config { - + + - - - + - - + + + + diff --git a/repos/gems/run/nano3d.run b/repos/gems/run/nano3d.run index 7ec6f7e4e1..4433122293 100644 --- a/repos/gems/run/nano3d.run +++ b/repos/gems/run/nano3d.run @@ -31,12 +31,11 @@ append config { - + + - - - + @@ -46,8 +45,10 @@ append config { - - + + + + diff --git a/repos/gems/run/sculpt.run b/repos/gems/run/sculpt.run index f7031210f4..ede18bb306 100644 --- a/repos/gems/run/sculpt.run +++ b/repos/gems/run/sculpt.run @@ -254,13 +254,13 @@ install_config { - - + + + - @@ -269,7 +269,7 @@ install_config { - + @@ -277,10 +277,9 @@ install_config { - - - - + + + diff --git a/repos/gems/run/sculpt/nitpicker.config b/repos/gems/run/sculpt/nitpicker.config index 9d8c3ea805..c043f2d17f 100644 --- a/repos/gems/run/sculpt/nitpicker.config +++ b/repos/gems/run/sculpt/nitpicker.config @@ -1,6 +1,8 @@ - + + + diff --git a/repos/gems/run/terminal_log.run b/repos/gems/run/terminal_log.run index c2e117542d..522229835e 100644 --- a/repos/gems/run/terminal_log.run +++ b/repos/gems/run/terminal_log.run @@ -40,26 +40,25 @@ install_config { - + + - - - + - - + + + - - + diff --git a/repos/gems/run/text_area.run b/repos/gems/run/text_area.run index e800f503dd..29dc3d9ae8 100644 --- a/repos/gems/run/text_area.run +++ b/repos/gems/run/text_area.run @@ -40,12 +40,11 @@ install_config { - + + - - - + @@ -59,8 +58,9 @@ install_config { - - + + + diff --git a/repos/gems/run/text_painter.run b/repos/gems/run/text_painter.run index c4e5dd49a6..f751616ab6 100644 --- a/repos/gems/run/text_painter.run +++ b/repos/gems/run/text_painter.run @@ -5,6 +5,8 @@ import_from_depot [depot_user]/src/[base_src] \ [depot_user]/src/init \ [depot_user]/src/libc \ [depot_user]/src/vfs \ + [depot_user]/src/nitpicker \ + [depot_user]/src/gui_fb \ [depot_user]/raw/ttf-bitstream-vera-minimal install_config { @@ -36,12 +38,36 @@ install_config { - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -70,6 +96,10 @@ install_config { build { server/vfs test/text_painter lib/vfs/ttf } +set fd [open [run_dir]/genode/focus w] +puts $fd " \" domain=\"default\"/>" +close $fd + build_boot_image { vfs test-text_painter vfs_ttf.lib.so } run_genode_until forever diff --git a/repos/gems/run/wm.run b/repos/gems/run/wm.run index 8a7aeba543..8183a24ac3 100644 --- a/repos/gems/run/wm.run +++ b/repos/gems/run/wm.run @@ -43,18 +43,19 @@ install_config { - + + - - - + - - + + + + diff --git a/repos/gems/src/app/driver_manager/main.cc b/repos/gems/src/app/driver_manager/main.cc index 149911a717..b29fb7fa81 100644 --- a/repos/gems/src/app/driver_manager/main.cc +++ b/repos/gems/src/app/driver_manager/main.cc @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -128,13 +128,11 @@ struct Driver_manager::Intel_fb_driver : Device_driver _gen_common_start_node_content(xml, "intel_fb_drv", "intel_fb_drv", Ram_quota{42*1024*1024}, Cap_quota{800}, Priority{0}); - _gen_provides_node(xml); xml.node("route", [&] () { _gen_config_route(xml, "fb_drv.config"); _gen_default_parent_route(xml); }); }); - _gen_forwarded_service(xml, "intel_fb_drv"); } }; @@ -147,13 +145,11 @@ struct Driver_manager::Vesa_fb_driver : Device_driver _gen_common_start_node_content(xml, "vesa_fb_drv", "vesa_fb_drv", Ram_quota{8*1024*1024}, Cap_quota{100}, Priority{-1}); - _gen_provides_node(xml); xml.node("route", [&] () { _gen_config_route(xml, "fb_drv.config"); _gen_default_parent_route(xml); }); }); - _gen_forwarded_service(xml, "vesa_fb_drv"); } }; @@ -193,13 +189,11 @@ struct Driver_manager::Boot_fb_driver : Device_driver _gen_common_start_node_content(xml, "fb_boot_drv", "fb_boot_drv", _ram_quota, Cap_quota{100}, Priority{-1}); - _gen_provides_node(xml); xml.node("route", [&] () { _gen_config_route(xml, "fb_drv.config"); _gen_default_parent_route(xml); }); }); - _gen_forwarded_service(xml, "fb_boot_drv"); } }; @@ -538,6 +532,7 @@ void Driver_manager::Main::_generate_init_config(Reporter &init_config) const _gen_parent_service_xml(xml, Platform::Session::service_name()); _gen_parent_service_xml(xml, Report::Session::service_name()); _gen_parent_service_xml(xml, Usb::Session::service_name()); + _gen_parent_service_xml(xml, Capture::Session::service_name()); }); diff --git a/repos/gems/src/test/driver_manager/main.cc b/repos/gems/src/test/driver_manager/main.cc index b330f76b8f..6479b217b5 100644 --- a/repos/gems/src/test/driver_manager/main.cc +++ b/repos/gems/src/test/driver_manager/main.cc @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -32,6 +31,7 @@ struct Test::Main Attached_rom_dataspace _config { _env, "config" }; Attached_rom_dataspace _block_devices { _env, "block_devices" }; + Attached_rom_dataspace _displays { _env, "displays" }; static bool _attribute_matches(char const *attr, Xml_node expected, Xml_node checked) { @@ -113,6 +113,14 @@ struct Test::Main Block::Connection<> block(_env, &packet_alloc, 128*1024, label.string()); }); + if (_config.xml().has_sub_node("check_displays")) { + _displays.update(); + if (!_displays.xml().has_sub_node("display")) + return; + + log("available displays: ", _displays.xml()); + } + log("all expected devices present and accessible"); } @@ -121,12 +129,6 @@ struct Test::Main Main(Env &env) : _env(env) { - if (_config.xml().has_sub_node("check_framebuffer")) { - log("connect to framebuffer driver"); - Framebuffer::Mode mode { .area = { 640, 480 } }; - Framebuffer::Connection fb(_env, mode); - } - if (_config.xml().has_sub_node("check_input")) { log("connect to input driver"); Input::Connection input(_env); diff --git a/repos/libports/recipes/src/vesa_drv/used_apis b/repos/libports/recipes/src/vesa_drv/used_apis index 6a2f674179..744efe168d 100644 --- a/repos/libports/recipes/src/vesa_drv/used_apis +++ b/repos/libports/recipes/src/vesa_drv/used_apis @@ -3,4 +3,4 @@ os blit platform_session timer_session -framebuffer_session +capture_session diff --git a/repos/libports/run/mesa.inc b/repos/libports/run/mesa.inc index bf4c028179..f4d4fb31c4 100644 --- a/repos/libports/run/mesa.inc +++ b/repos/libports/run/mesa.inc @@ -53,18 +53,18 @@ set config { - + + - - - + - - + + + diff --git a/repos/libports/run/mupdf.run b/repos/libports/run/mupdf.run index 4f1085bbdb..02a9e39af4 100644 --- a/repos/libports/run/mupdf.run +++ b/repos/libports/run/mupdf.run @@ -39,18 +39,19 @@ set config { - + + - - - + - - + + + + diff --git a/repos/libports/run/qt5_common.inc b/repos/libports/run/qt5_common.inc index d2b1533671..24e1005f2e 100644 --- a/repos/libports/run/qt5_common.inc +++ b/repos/libports/run/qt5_common.inc @@ -177,26 +177,28 @@ proc qt5_start_nodes { } { - + + - - - + - + - + + + - + diff --git a/repos/libports/src/drivers/framebuffer/vesa/main.cc b/repos/libports/src/drivers/framebuffer/vesa/main.cc index 4ec88818f1..cb6079df31 100644 --- a/repos/libports/src/drivers/framebuffer/vesa/main.cc +++ b/repos/libports/src/drivers/framebuffer/vesa/main.cc @@ -7,7 +7,7 @@ */ /* - * Copyright (C) 2007-2017 Genode Labs GmbH + * Copyright (C) 2007-2020 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. @@ -17,231 +17,150 @@ #include #include #include -#include -#include #include -#include -#include #include -#include +#include +#include +#include /* local includes */ #include "framebuffer.h" - -namespace Framebuffer { - struct Session_component; - struct Root; +namespace Vesa_driver { + using namespace Genode; struct Main; - - using Genode::size_t; - using Genode::min; - using Genode::max; - using Genode::Dataspace_capability; - using Genode::Attached_rom_dataspace; - using Genode::Attached_ram_dataspace; } -class Framebuffer::Session_component : public Genode::Rpc_object +struct Vesa_driver::Main { - private: + using Pixel = Capture::Pixel; + using Area = Capture::Area; - Genode::Env &_env; + Env &_env; - unsigned const _scr_width, _scr_height, _scr_depth; - - Timer::Connection _timer { _env }; - - /* dataspace of physical frame buffer */ - Dataspace_capability _fb_cap; - void *_fb_addr; - - /* dataspace uses a back buffer (if '_buffered' is true) */ - Genode::Constructible _bb; - - void _refresh_buffered(int x, int y, int w, int h) - { - /* clip specified coordinates against screen boundaries */ - int x2 = min(x + w - 1, (int)_scr_width - 1), - y2 = min(y + h - 1, (int)_scr_height - 1); - int x1 = max(x, 0), - y1 = max(y, 0); - if (x1 > x2 || y1 > y2) return; - - /* determine bytes per pixel */ - int bypp = 0; - if (_scr_depth == 32) bypp = 4; - if (!bypp) return; - - /* copy pixels from back buffer to physical frame buffer */ - char *src = _bb->local_addr() + bypp*(_scr_width*y1 + x1), - *dst = (char *)_fb_addr + bypp*(_scr_width*y1 + x1); - - blit(src, bypp*_scr_width, dst, bypp*_scr_width, - bypp*(x2 - x1 + 1), y2 - y1 + 1); - } - - bool _buffered() const { return _bb.constructed(); } - - public: - - /** - * Constructor - */ - Session_component(Genode::Env &env, - unsigned scr_width, unsigned scr_height, unsigned scr_depth, - Dataspace_capability fb_cap, bool buffered) - : - _env(env), - _scr_width(scr_width), _scr_height(scr_height), _scr_depth(scr_depth), - _fb_cap(fb_cap) - { - if (!buffered) return; - - size_t const bb_size = _scr_width*_scr_height*_scr_depth/8; - try { _bb.construct(env.ram(), env.rm(), bb_size); } - catch (...) { - Genode::warning("could not allocate back buffer, disabled buffered output"); - return; - } - - _fb_addr = env.rm().attach(_fb_cap); - - Genode::log("using buffered output"); - } - - /** - * Destructor - */ - ~Session_component() - { - if (_buffered()) { - _bb.destruct(); - _env.rm().detach(_fb_addr); - } - } + Heap _heap { _env.ram(), _env.rm() }; - /*********************************** - ** Framebuffer session interface ** - ***********************************/ + /* + * Config + */ - Dataspace_capability dataspace() override - { - return _buffered() ? Dataspace_capability(_bb->cap()) - : Dataspace_capability(_fb_cap); - } + Attached_rom_dataspace _config { _env, "config" }; - Mode mode() const override - { - return Mode { .area = { _scr_width, _scr_height } }; - } + Area _size { 1, 1 }; - void mode_sigh(Genode::Signal_context_capability) override { } + void _handle_config(); - void sync_sigh(Genode::Signal_context_capability sigh) override - { - _timer.sigh(sigh); - _timer.trigger_periodic(10*1000); - } - - void refresh(int x, int y, int w, int h) override - { - if (_buffered()) - _refresh_buffered(x, y, w, h); - } -}; + Signal_handler
_config_handler { _env.ep(), *this, &Main::_handle_config }; -/** - * Shortcut for single-client root component - */ -typedef Genode::Root_component Root_component; + /* + * Capture + */ -class Framebuffer::Root : public Root_component -{ - private: + Capture::Connection _capture { _env }; - Genode::Env &_env; - - Attached_rom_dataspace const &_config; - - unsigned _session_arg(char const *attr_name, char const *args, - char const *arg_name, unsigned default_value) - { - /* try to obtain value from config file */ - unsigned result = _config.xml().attribute_value(attr_name, - default_value); - - /* check session argument to override value from config file */ - return Genode::Arg_string::find_arg(args, arg_name).ulong_value(result); - } - - protected: - - Session_component *_create_session(char const *args) override - { - unsigned scr_width = _session_arg("width", args, "fb_width", 0); - unsigned scr_height = _session_arg("height", args, "fb_height", 0); - unsigned const scr_depth = 32; - - bool const buffered = _config.xml().attribute_value("buffered", true); - - if (Framebuffer::set_mode(scr_width, scr_height, scr_depth) != 0) { - Genode::warning("Could not set vesa mode ", - scr_width, "x", scr_height, "@", scr_depth); - throw Genode::Service_denied(); - } - - Genode::log("using video mode: ", - scr_width, "x", scr_height, "@", scr_depth); - - return new (md_alloc()) Session_component(_env, - scr_width, scr_height, scr_depth, - Framebuffer::hw_framebuffer(), - buffered); - } - - public: - - Root(Genode::Env &env, Genode::Allocator &alloc, - Attached_rom_dataspace const &config) - : - Root_component(&env.ep().rpc_ep(), &alloc), - _env(env), _config(config) - { } -}; + Constructible _captured_screen { }; -struct Framebuffer::Main -{ - Genode::Env &env; + /* + * Timer + */ - Genode::Heap heap { env.ram(), env.rm() }; + Timer::Connection _timer { _env }; - Attached_rom_dataspace config { env, "config" }; + Signal_handler
_timer_handler { _env.ep(), *this, &Main::_handle_timer }; - Root root { env, heap, config }; + void _handle_timer(); - Main(Genode::Env &env) : env(env) + + /* + * Driver + */ + + bool const _framebuffer_initialized = ( Framebuffer::init(_env, _heap), true ); + + Constructible _fb_ds { }; + + Main(Env &env) : _env(env) { - Genode::log("modified"); - try { Framebuffer::init(env, heap); } catch (...) { - Genode::error("H/W driver init failed"); - throw; - } + _config.sigh(_config_handler); + _timer.sigh(_timer_handler); - env.parent().announce(env.ep().manage(root)); + _handle_config(); } }; +void Vesa_driver::Main::_handle_timer() +{ + if (!_fb_ds.constructed()) + return; + + Surface surface(_fb_ds->local_addr(), _size); + + _captured_screen->apply_to_surface(surface); +} + + +void Vesa_driver::Main::_handle_config() +{ + _config.update(); + + Xml_node const config = _config.xml(); + + Area const configured_size { config.attribute_value("width", 0U), + config.attribute_value("height", 0U) }; + if (configured_size == _size) + return; + + _size = Area { }; + _fb_ds.destruct(); + _timer.trigger_periodic(0); + + /* set VESA mode */ + { + enum { BITS_PER_PIXEL = 32 }; + + struct Pretty_mode + { + Area size; + void print(Output &out) const { + Genode::print(out, "VESA mode ", size, "@", (int)BITS_PER_PIXEL); } + }; + + unsigned width = configured_size.w(), + height = configured_size.h(); + + if (Framebuffer::set_mode(width, height, BITS_PER_PIXEL) != 0) { + warning("could not set ", Pretty_mode{configured_size}); + return; + } + + /* + * Framebuffer::set_mode may return a size different from the passed + * argument. In paricular, when passing a size of (0,0), the function + * sets and returns the highest screen mode possible. + */ + _size = Area { width, height }; + + log("using ", Pretty_mode{_size}); + } + + /* enable pixel capturing */ + _fb_ds.construct(_env.rm(), Framebuffer::hw_framebuffer()); + _captured_screen.construct(_capture, _env.rm(), _size); + + unsigned long const period_ms = config.attribute_value("period_ms", 20U); + _timer.trigger_periodic(period_ms*1000); +} + + void Component::construct(Genode::Env &env) { /* XXX execute constructors of global statics */ env.exec_static_constructors(); - static Framebuffer::Main inst(env); + static Vesa_driver::Main inst(env); } diff --git a/repos/os/recipes/pkg/drivers_interactive-linux/archives b/repos/os/recipes/pkg/drivers_interactive-linux/archives index 98c969f10c..11d4a2de0a 100644 --- a/repos/os/recipes/pkg/drivers_interactive-linux/archives +++ b/repos/os/recipes/pkg/drivers_interactive-linux/archives @@ -1,3 +1,4 @@ _/src/fb_sdl _/src/input_filter +_/src/input_event_bridge _/raw/drivers_interactive-linux diff --git a/repos/os/recipes/raw/drivers_interactive-imx53_qsb/drivers.config b/repos/os/recipes/raw/drivers_interactive-imx53_qsb/drivers.config index 3d3564258d..f9b7f49345 100644 --- a/repos/os/recipes/raw/drivers_interactive-imx53_qsb/drivers.config +++ b/repos/os/recipes/raw/drivers_interactive-imx53_qsb/drivers.config @@ -10,13 +10,11 @@ + - - - @@ -59,7 +57,6 @@ - @@ -70,6 +67,7 @@ + @@ -77,10 +75,10 @@ - - - - + + + + diff --git a/repos/os/recipes/raw/drivers_interactive-linux/drivers.config b/repos/os/recipes/raw/drivers_interactive-linux/drivers.config index 330ea8a8ca..caafabec9f 100644 --- a/repos/os/recipes/raw/drivers_interactive-linux/drivers.config +++ b/repos/os/recipes/raw/drivers_interactive-linux/drivers.config @@ -5,21 +5,25 @@ + - - - + + + + + + + - - - - - + + + + @@ -27,7 +31,7 @@ - + diff --git a/repos/os/recipes/raw/drivers_interactive-pbxa9/drivers.config b/repos/os/recipes/raw/drivers_interactive-pbxa9/drivers.config index dda9b9fc43..8913739bef 100644 --- a/repos/os/recipes/raw/drivers_interactive-pbxa9/drivers.config +++ b/repos/os/recipes/raw/drivers_interactive-pbxa9/drivers.config @@ -7,13 +7,11 @@ + - - - @@ -64,25 +62,23 @@ - - - - - - + + + + + + - - - + diff --git a/repos/os/recipes/raw/drivers_interactive-pc/drivers.config b/repos/os/recipes/raw/drivers_interactive-pc/drivers.config index cf46aca1f4..d873d9f766 100644 --- a/repos/os/recipes/raw/drivers_interactive-pc/drivers.config +++ b/repos/os/recipes/raw/drivers_interactive-pc/drivers.config @@ -10,13 +10,11 @@ + - - - @@ -77,8 +75,7 @@ - - + @@ -89,6 +86,7 @@ + diff --git a/repos/os/recipes/src/boot_fb_drv/used_apis b/repos/os/recipes/src/boot_fb_drv/used_apis index 254aab69aa..bcecfa3ccd 100644 --- a/repos/os/recipes/src/boot_fb_drv/used_apis +++ b/repos/os/recipes/src/boot_fb_drv/used_apis @@ -1,5 +1,5 @@ base os blit -framebuffer_session +capture_session timer_session diff --git a/repos/os/recipes/src/fb_sdl/used_apis b/repos/os/recipes/src/fb_sdl/used_apis index 4fa949cf7a..4d37a38acc 100644 --- a/repos/os/recipes/src/fb_sdl/used_apis +++ b/repos/os/recipes/src/fb_sdl/used_apis @@ -1,7 +1,7 @@ base-linux base os -input_session -framebuffer_session +event_session timer_session +capture_session blit diff --git a/repos/os/recipes/src/imx53_qsb_drivers/used_apis b/repos/os/recipes/src/imx53_qsb_drivers/used_apis index a1d0fa1905..22164f3795 100644 --- a/repos/os/recipes/src/imx53_qsb_drivers/used_apis +++ b/repos/os/recipes/src/imx53_qsb_drivers/used_apis @@ -3,6 +3,6 @@ os blit platform_session gpio_session -framebuffer_session +capture_session input_session timer_session diff --git a/repos/os/recipes/src/pbxa9_drivers/used_apis b/repos/os/recipes/src/pbxa9_drivers/used_apis index ba05df6f1c..5392b0ccbd 100644 --- a/repos/os/recipes/src/pbxa9_drivers/used_apis +++ b/repos/os/recipes/src/pbxa9_drivers/used_apis @@ -1,6 +1,6 @@ base os -framebuffer_session +capture_session input_session platform_session timer_session diff --git a/repos/os/recipes/src/rpi_fb_drv/used_apis b/repos/os/recipes/src/rpi_fb_drv/used_apis index 4e3ce1a129..f263fb769e 100644 --- a/repos/os/recipes/src/rpi_fb_drv/used_apis +++ b/repos/os/recipes/src/rpi_fb_drv/used_apis @@ -2,4 +2,4 @@ base os blit platform_session -framebuffer_session +capture_session diff --git a/repos/os/run/demo.run b/repos/os/run/demo.run index 2b6432fe87..ade5358b1d 100644 --- a/repos/os/run/demo.run +++ b/repos/os/run/demo.run @@ -46,12 +46,11 @@ install_config { - + + - - - + @@ -69,16 +68,18 @@ install_config { - + + + - + diff --git a/repos/os/run/fb_bench.run b/repos/os/run/fb_bench.run index ae366b32ac..9f6031142a 100644 --- a/repos/os/run/fb_bench.run +++ b/repos/os/run/fb_bench.run @@ -15,6 +15,8 @@ if {[get_cmd_switch --autopilot] && [have_spec linux]} { create_boot_directory import_from_depot [depot_user]/src/[base_src] \ [depot_user]/pkg/[drivers_interactive_pkg] \ + [depot_user]/src/nitpicker \ + [depot_user]/src/gui_fb \ [depot_user]/src/init build { test/fb_bench } @@ -45,12 +47,35 @@ install_config { - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -60,9 +85,14 @@ install_config { - RAM. --> + } +set fd [open [run_dir]/genode/focus w] +puts $fd " \" domain=\"default\"/>" +close $fd + build_boot_image { test-fb_bench } # disable QEMU graphic to enable testing on our machines without SDL and X diff --git a/repos/os/run/framebuffer.run b/repos/os/run/framebuffer.run index ec09d79b86..af4b9418bb 100644 --- a/repos/os/run/framebuffer.run +++ b/repos/os/run/framebuffer.run @@ -32,16 +32,17 @@ install_config { - + + - - - + + + } diff --git a/repos/os/run/loader.run b/repos/os/run/loader.run index dd4af94cd5..2e8ed9f9b7 100644 --- a/repos/os/run/loader.run +++ b/repos/os/run/loader.run @@ -36,18 +36,18 @@ install_config { - + + - - - + - - + + + diff --git a/repos/os/run/pointer.run b/repos/os/run/pointer.run index b49b2c8b63..f99eae560e 100644 --- a/repos/os/run/pointer.run +++ b/repos/os/run/pointer.run @@ -12,6 +12,7 @@ set build_components { server/report_rom server/dynamic_rom server/nitpicker + server/input_event_bridge app/pointer test/pointer test/nitpicker @@ -49,22 +50,31 @@ set config { - - + + - + - + - - - - - + - + + + + + + + + + + + + + + @@ -85,8 +95,9 @@ set config { - - + + + @@ -102,7 +113,6 @@ set config { - @@ -282,6 +292,7 @@ set boot_modules { pointer test-pointer testnit + input_event_bridge } # "lsort -unique" removes duplicates but core must be first diff --git a/repos/os/src/drivers/framebuffer/boot/framebuffer.cc b/repos/os/src/drivers/framebuffer/boot/framebuffer.cc deleted file mode 100644 index 15fdf9cdcf..0000000000 --- a/repos/os/src/drivers/framebuffer/boot/framebuffer.cc +++ /dev/null @@ -1,97 +0,0 @@ -/* - * \brief Framebuffer driver that uses a framebuffer supplied by the core rom. - * \author Johannes Kliemann - * \date 2017-06-12 - */ - -/* - * Copyright (C) 2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#include -#include -#include - -using namespace Framebuffer; - -Session_component::Session_component(Genode::Env &env, - Genode::Xml_node pinfo) -: _env(env) -{ - enum { RGB_COLOR = 1 }; - - unsigned fb_boot_type = 0; - - try { - Genode::Xml_node fb = pinfo.sub_node("boot").sub_node("framebuffer"); - - fb.attribute("phys").value(_core_fb.addr); - fb.attribute("width").value(_core_fb.width); - fb.attribute("height").value(_core_fb.height); - fb.attribute("bpp").value(_core_fb.bpp); - fb.attribute("pitch").value(_core_fb.pitch); - fb_boot_type = fb.attribute_value("type", 0U); - } catch (...) { - Genode::error("No boot framebuffer information available."); - throw Genode::Service_denied(); - } - - Genode::log("Framebuffer with ", _core_fb.width, "x", _core_fb.height, - "x", _core_fb.bpp, " @ ", (void*)_core_fb.addr, - " type=", fb_boot_type, " pitch=", _core_fb.pitch); - - if (_core_fb.bpp != 32 || fb_boot_type != RGB_COLOR ) { - Genode::error("unsupported resolution (bpp or/and type)"); - throw Genode::Service_denied(); - } - - _fb_mem.construct(_env, _core_fb.addr, _core_fb.pitch * _core_fb.height, - true); - - _fb_mode = Mode { .area = { _core_fb.width, _core_fb.height } }; - - _fb_ram.construct(_env.ram(), _env.rm(), _core_fb.width * _core_fb.height * - _fb_mode.bytes_per_pixel()); -} - -Mode Session_component::mode() const { return _fb_mode; } - -void Session_component::mode_sigh(Genode::Signal_context_capability) { } - -void Session_component::sync_sigh(Genode::Signal_context_capability scc) -{ - timer.sigh(scc); - timer.trigger_periodic(10*1000); -} - -void Session_component::refresh(int const x, int const y, int const w, int const h) -{ - using namespace Genode; - - int const width = _core_fb.width; - int const height = _core_fb.height; - unsigned const bpp = 4; - unsigned const pitch = _core_fb.pitch; - - /* clip specified coordinates against screen boundaries */ - int const x2 = min(x + w - 1, width - 1), - y2 = min(y + h - 1, height - 1); - int const x1 = max(x, 0), - y1 = max(y, 0); - if (x1 > x2 || y1 > y2) - return; - - /* copy pixels from back buffer to physical frame buffer */ - char const *src = _fb_ram->local_addr() + bpp*width*y1 + bpp*x1; - char *dst = _fb_mem->local_addr() + pitch*y1 + bpp*x1; - - blit(src, bpp*width, dst, pitch, bpp*(x2 - x1 + 1), y2 - y1 + 1); -} - -Genode::Dataspace_capability Session_component::dataspace() -{ - return _fb_ram->cap(); -} diff --git a/repos/os/src/drivers/framebuffer/boot/include/framebuffer.h b/repos/os/src/drivers/framebuffer/boot/include/framebuffer.h deleted file mode 100644 index 0cdcaa0fb8..0000000000 --- a/repos/os/src/drivers/framebuffer/boot/include/framebuffer.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * \brief Framebuffer driver that uses a framebuffer supplied by the core rom. - * \author Johannes Kliemann - * \date 2017-06-12 - */ - -/* - * Copyright (C) 2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _FRAMEBUFFER_H_ -#define _FRAMEBUFFER_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Framebuffer { - - class Session_component; -} - -class Framebuffer::Session_component : public Genode::Rpc_object -{ - private: - - Genode::Env &_env; - - struct Fb_desc - { - Genode::uint64_t addr; - Genode::uint32_t width; - Genode::uint32_t height; - Genode::uint32_t pitch; - Genode::uint32_t bpp; - } _core_fb { }; - - Mode _fb_mode { }; - - Genode::Constructible _fb_mem { }; - Genode::Constructible _fb_ram { }; - - Timer::Connection timer { _env }; - - public: - Session_component(Genode::Env &, Genode::Xml_node); - Mode mode() const override; - void mode_sigh(Genode::Signal_context_capability) override; - void sync_sigh(Genode::Signal_context_capability) override; - void refresh(int, int, int, int) override; - Genode::Dataspace_capability dataspace() override; -}; - -#endif // _FRAMEBUFFER_H_ diff --git a/repos/os/src/drivers/framebuffer/boot/main.cc b/repos/os/src/drivers/framebuffer/boot/main.cc index 5d681fceaf..4551ba1e98 100644 --- a/repos/os/src/drivers/framebuffer/boot/main.cc +++ b/repos/os/src/drivers/framebuffer/boot/main.cc @@ -1,11 +1,12 @@ /* * \brief Framebuffer driver that uses a framebuffer supplied by the core rom. * \author Johannes Kliemann + * \author Norman Feske * \date 2017-06-12 */ /* - * Copyright (C) 2017 Genode Labs GmbH + * Copyright (C) 2020 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. @@ -13,35 +14,102 @@ #include #include +#include #include -#include +#include +#include -#include +namespace Framebuffer { + using namespace Genode; + struct Main; +} -struct Main { - Genode::Env &env; +struct Framebuffer::Main +{ + using Area = Capture::Area; + using Pixel = Capture::Pixel; - Genode::Attached_rom_dataspace pinfo { - env, - "platform_info" - }; + Env &_env; - Framebuffer::Session_component fb { - env, - pinfo.xml(), - }; + Attached_rom_dataspace _platform_info { _env, "platform_info" }; - Genode::Static_root fb_root {env.ep().manage(fb)}; - - Main(Genode::Env &env) : env(env) + struct Info { - env.parent().announce(env.ep().manage(fb_root)); + addr_t addr; + Area size; + unsigned bpp; + unsigned pitch; + unsigned type; + + static Info from_platform_info(Xml_node const &node) + { + Info result { }; + node.with_sub_node("boot", [&] (Xml_node const &boot) { + boot.with_sub_node("framebuffer", [&] (Xml_node const &fb) { + result = { + .addr = fb.attribute_value("phys", 0UL), + .size = { fb.attribute_value("width", 0U), + fb.attribute_value("height", 0U) }, + .bpp = fb.attribute_value("bpp", 0U), + .pitch = fb.attribute_value("pitch", 0U), + .type = fb.attribute_value("type", 0U) + }; + }); + }); + return result; + } + + enum { TYPE_RGB_COLOR = 1 }; + + void print(Output &out) const + { + Genode::print(out, size, "x", bpp, " @ ", (void*)addr, " " + "type=", type, " pitch=", pitch); + } + }; + + Info const _info = Info::from_platform_info(_platform_info.xml()); + + void _check_info() const + { + if (_info.bpp != 32 || _info.type != Info::TYPE_RGB_COLOR ) { + error("unsupported resolution (bpp or/and type), platform info:\n", + _platform_info.xml()); + throw Exception(); + } + } + + bool const _checked_info = ( _check_info(), true ); + + Attached_io_mem_dataspace _fb_ds { _env, _info.addr, + _info.pitch*_info.size.h(), true }; + + Capture::Connection _capture { _env }; + + Capture::Connection::Screen _captured_screen { _capture, _env.rm(), _info.size }; + + Timer::Connection _timer { _env }; + + Signal_handler
_timer_handler { _env.ep(), *this, &Main::_handle_timer }; + + void _handle_timer() + { + Area const phys_size { (uint32_t)(_info.pitch/sizeof(Pixel)), _info.size.h() }; + + Surface surface(_fb_ds.local_addr(), phys_size); + + _captured_screen.apply_to_surface(surface); + } + + Main(Env &env) : _env(env) + { + log("using boot framebuffer: ", _info); + + _timer.sigh(_timer_handler); + _timer.trigger_periodic(10*1000); } }; -void Component::construct(Genode::Env &env) { - static Main inst(env); - -} +void Component::construct(Genode::Env &env) { static Framebuffer::Main inst(env); } diff --git a/repos/os/src/drivers/framebuffer/boot/target.mk b/repos/os/src/drivers/framebuffer/boot/target.mk index 884d4b3726..4c449ef512 100644 --- a/repos/os/src/drivers/framebuffer/boot/target.mk +++ b/repos/os/src/drivers/framebuffer/boot/target.mk @@ -1,4 +1,3 @@ TARGET = fb_boot_drv LIBS = base blit -SRC_CC = main.cc framebuffer.cc -INC_DIR += $(PRG_DIR)/include +SRC_CC = main.cc diff --git a/repos/os/src/drivers/framebuffer/pl11x/main.cc b/repos/os/src/drivers/framebuffer/pl11x/main.cc index 81d9f05635..4c17090b8f 100644 --- a/repos/os/src/drivers/framebuffer/pl11x/main.cc +++ b/repos/os/src/drivers/framebuffer/pl11x/main.cc @@ -16,21 +16,15 @@ #include #include #include -#include -#include -#include #include #include #include +#include +#include +#include - -/*********************************************** - ** Implementation of the framebuffer service ** - ***********************************************/ - -namespace Framebuffer +namespace Pl11x_driver { - enum { SCR_WIDTH = 640, SCR_HEIGHT = 480, @@ -45,154 +39,51 @@ namespace Framebuffer FRAMEBUFFER_SIZE = SCR_WIDTH*SCR_HEIGHT*BYTES_PER_PIXEL, }; - class Session_component; - using namespace Genode; class Main; } -class Framebuffer::Session_component : - public Genode::Rpc_object + +struct Pl11x_driver::Main { - private: + using Area = Capture::Area; - Ram_dataspace_capability _fb_ds_cap; - addr_t _regs_base; - addr_t _sys_regs_base; - Timer::Connection _timer; + Env &_env; - enum { - /** - * Bit definitions of the lcd control register - */ - CTRL_ENABLED = 1 << 0, - CTRL_BPP_24 = 5 << 1, - CTRL_TFT = 1 << 5, - CTRL_BGR = 1 << 8, - CTRL_POWER = 1 << 11, - CTRL_VCOMP = 1 << 12, - - /** - * Bit definitions for CLCDC timing. - */ - CLCDC_IVS = 1 << 11, - CLCDC_IHS = 1 << 12, - CLCDC_BCD = 1 << 26, - }; - - enum Sp810_defs { - SP810_REG_OSCCLCD = 0x1c, - SP810_REG_LOCK = 0x20, - }; - - enum Pl11x_defs { - PL11X_REG_TIMING0 = 0, - PL11X_REG_TIMING1 = 1, - PL11X_REG_TIMING2 = 2, - PL11X_REG_TIMING3 = 3, - PL11X_REG_UPBASE = 4, - PL11X_REG_LPBASE = 5, - PL11X_REG_CTRL = 6, - PL11X_REG_IMSC = 7, - }; - - void sys_reg_write(unsigned reg, long value) { - *(volatile long *)(_sys_regs_base + sizeof(long)*reg) = value; } - - long sys_reg_read(unsigned reg) { - return *(volatile long *)(_sys_regs_base + sizeof(long)*reg); } - - void reg_write(unsigned reg, long value) { - *(volatile long *)(_regs_base + sizeof(long)*reg) = value; } - - long reg_read(unsigned reg) { - return *(volatile long *)(_regs_base + sizeof(long)*reg); } - - public: - - /** - * Constructor - */ - Session_component(Env & env, - void * regs_base, - void * sys_regs_base, - Ram_dataspace_capability fb_ds_cap, - Genode::addr_t fb_ds_bus_addr) - : _fb_ds_cap(fb_ds_cap), - _regs_base((addr_t)regs_base), - _sys_regs_base((addr_t)sys_regs_base), - _timer(env) - { - using namespace Genode; - - uint32_t tim0 = (SCR_WIDTH/16 - 1) << 2 - | (HSYNC_LEN - 1) << 8 - | (RIGHT_MARGIN - 1) << 16 - | (LEFT_MARGIN - 1) << 24; - uint32_t tim1 = (SCR_HEIGHT - 1) - | (VSYNC_LEN - 1) << 10 - | LOWER_MARGIN << 16 - | UPPER_MARGIN << 24; - uint32_t tim2 = ((SCR_WIDTH - 1) << 16) - | CLCDC_IVS | CLCDC_IHS | CLCDC_BCD; - uint32_t tim3 = 0; - uint32_t ctrl = reg_read(PL11X_REG_CTRL); - - /* reset video if already enabled */ - if (ctrl & CTRL_POWER) { - ctrl &= ~CTRL_POWER; - reg_write(PL11X_REG_CTRL, ctrl); - _timer.msleep(100); - } - if (ctrl & CTRL_ENABLED) { - ctrl &= ~CTRL_ENABLED; - reg_write(PL11X_REG_CTRL, ctrl); - _timer.msleep(100); - } - - ctrl = CTRL_BGR | CTRL_ENABLED | CTRL_TFT | CTRL_VCOMP | CTRL_BPP_24; - - /* init color-lcd oscillator */ - sys_reg_write(SP810_REG_LOCK, 0xa05f); - sys_reg_write(SP810_REG_OSCCLCD, 0x2c77); - sys_reg_write(SP810_REG_LOCK, 0); - - /* init video timing */ - reg_write(PL11X_REG_TIMING0, tim0); - reg_write(PL11X_REG_TIMING1, tim1); - reg_write(PL11X_REG_TIMING2, tim2); - reg_write(PL11X_REG_TIMING3, tim3); - - /* set framebuffer address and ctrl register */ - reg_write(PL11X_REG_UPBASE, fb_ds_bus_addr); - reg_write(PL11X_REG_LPBASE, 0); - reg_write(PL11X_REG_IMSC, 0); - reg_write(PL11X_REG_CTRL, ctrl); - _timer.msleep(100); - - /* power on */ - reg_write(PL11X_REG_CTRL, ctrl | CTRL_POWER); - } - - Genode::Dataspace_capability dataspace() override { return _fb_ds_cap; } - - Mode mode() const override { return Mode { .area { SCR_WIDTH, SCR_HEIGHT } }; } - - void mode_sigh(Genode::Signal_context_capability) override { } - - void sync_sigh(Genode::Signal_context_capability sigh) override - { - _timer.sigh(sigh); - _timer.trigger_periodic(10*1000); - } - - void refresh(int, int, int, int) override { } -}; + Area const _size { SCR_WIDTH, SCR_HEIGHT }; -struct Framebuffer::Main -{ - Env & _env; + /* + * Capture + */ + + Capture::Connection _capture { _env }; + + Capture::Connection::Screen _captured_screen { _capture, _env.rm(), _size }; + + + /* + * Timer + */ + + Timer::Connection _timer { _env }; + + Signal_handler
_timer_handler { _env.ep(), *this, &Main::_handle_timer }; + + void _handle_timer() + { + using Pixel = Capture::Pixel; + + Surface surface(_fb_ds.local_addr(), _size); + + _captured_screen.apply_to_surface(surface); + } + + + /* + * Driver + */ + Platform::Connection _platform { _env }; Platform::Device_client _pl11x_dev { _platform.device_by_property("compatible", "arm,pl111") }; @@ -204,34 +95,122 @@ struct Framebuffer::Main _sp810_dev.io_mem_dataspace() }; Ram_dataspace_capability _fb_ds_cap { _platform.alloc_dma_buffer(FRAMEBUFFER_SIZE) }; + Attached_dataspace _fb_ds { _env.rm(), _fb_ds_cap }; - Session_component _fb_session { _env, - _lcd_io_mem.local_addr(), - _sys_mem.local_addr(), - _fb_ds_cap, - _platform.bus_addr_dma_buffer(_fb_ds_cap) }; - - Static_root _fb_root { _env.ep().manage(_fb_session) }; + void _init_device(); Main(Env &env) : _env(env) { - log("--- pl11x framebuffer driver ---\n"); + _init_device(); - /* announce service */ - _env.parent().announce(env.ep().manage(_fb_root)); + _timer.sigh(_timer_handler); + _timer.trigger_periodic(20*1000); + } +}; + + +void Pl11x_driver::Main::_init_device() +{ + enum { + /** + * Bit definitions of the lcd control register + */ + CTRL_ENABLED = 1 << 0, + CTRL_BPP_24 = 5 << 1, + CTRL_TFT = 1 << 5, + CTRL_BGR = 1 << 8, + CTRL_POWER = 1 << 11, + CTRL_VCOMP = 1 << 12, + + /** + * Bit definitions for CLCDC timing. + */ + CLCDC_IVS = 1 << 11, + CLCDC_IHS = 1 << 12, + CLCDC_BCD = 1 << 26, + }; + + enum Sp810_defs { + SP810_REG_OSCCLCD = 0x1c, + SP810_REG_LOCK = 0x20, + }; + + enum Pl11x_defs { + PL11X_REG_TIMING0 = 0, + PL11X_REG_TIMING1 = 1, + PL11X_REG_TIMING2 = 2, + PL11X_REG_TIMING3 = 3, + PL11X_REG_UPBASE = 4, + PL11X_REG_LPBASE = 5, + PL11X_REG_CTRL = 6, + PL11X_REG_IMSC = 7, + }; + + addr_t const regs_base = (addr_t)_lcd_io_mem.local_addr(); + addr_t const sys_regs_base = (addr_t)_sys_mem.local_addr(); + + auto sys_reg_write = [&] (unsigned reg, long value) { + *(volatile long *)(sys_regs_base + sizeof(long)*reg) = value; }; + + auto reg_write = [&] (unsigned reg, long value) { + *(volatile long *)(regs_base + sizeof(long)*reg) = value; }; + + auto reg_read = [&] (unsigned reg) { + return *(volatile long *)(regs_base + sizeof(long)*reg); }; + + uint32_t const tim0 = (SCR_WIDTH/16 - 1) << 2 + | (HSYNC_LEN - 1) << 8 + | (RIGHT_MARGIN - 1) << 16 + | (LEFT_MARGIN - 1) << 24; + uint32_t const tim1 = (SCR_HEIGHT - 1) + | (VSYNC_LEN - 1) << 10 + | LOWER_MARGIN << 16 + | UPPER_MARGIN << 24; + uint32_t const tim2 = ((SCR_WIDTH - 1) << 16) + | CLCDC_IVS | CLCDC_IHS | CLCDC_BCD; + uint32_t const tim3 = 0; + + uint32_t ctrl = reg_read(PL11X_REG_CTRL); + + /* reset video if already enabled */ + if (ctrl & CTRL_POWER) { + ctrl &= ~CTRL_POWER; + reg_write(PL11X_REG_CTRL, ctrl); + _timer.msleep(100); + } + if (ctrl & CTRL_ENABLED) { + ctrl &= ~CTRL_ENABLED; + reg_write(PL11X_REG_CTRL, ctrl); + _timer.msleep(100); } - private: + ctrl = CTRL_BGR | CTRL_ENABLED | CTRL_TFT | CTRL_VCOMP | CTRL_BPP_24; - /* - * Noncopyable - */ - Main(Main const &); - Main &operator = (Main const &); -}; + /* init color-lcd oscillator */ + sys_reg_write(SP810_REG_LOCK, 0xa05f); + sys_reg_write(SP810_REG_OSCCLCD, 0x2c77); + sys_reg_write(SP810_REG_LOCK, 0); + + /* init video timing */ + reg_write(PL11X_REG_TIMING0, tim0); + reg_write(PL11X_REG_TIMING1, tim1); + reg_write(PL11X_REG_TIMING2, tim2); + reg_write(PL11X_REG_TIMING3, tim3); + + /* set framebuffer address and ctrl register */ + addr_t const fb_dma_base = (addr_t)_platform.bus_addr_dma_buffer(_fb_ds_cap); + reg_write(PL11X_REG_UPBASE, fb_dma_base); + reg_write(PL11X_REG_LPBASE, 0); + reg_write(PL11X_REG_IMSC, 0); + reg_write(PL11X_REG_CTRL, ctrl); + _timer.msleep(100); + + /* power on */ + reg_write(PL11X_REG_CTRL, ctrl | CTRL_POWER); +} void Component::construct(Genode::Env &env) { - static Framebuffer::Main main(env); + static Pl11x_driver::Main main(env); } diff --git a/repos/os/src/drivers/framebuffer/pl11x/target.mk b/repos/os/src/drivers/framebuffer/pl11x/target.mk index 7f4e1f99ce..a26af45428 100644 --- a/repos/os/src/drivers/framebuffer/pl11x/target.mk +++ b/repos/os/src/drivers/framebuffer/pl11x/target.mk @@ -1,4 +1,4 @@ TARGET = pl11x_fb_drv REQUIRES = arm_v7 SRC_CC = main.cc -LIBS = base +LIBS = base blit diff --git a/repos/os/src/drivers/framebuffer/spec/imx53/driver.h b/repos/os/src/drivers/framebuffer/spec/imx53/driver.h index c27f91cc55..1ba7fd3525 100644 --- a/repos/os/src/drivers/framebuffer/spec/imx53/driver.h +++ b/repos/os/src/drivers/framebuffer/spec/imx53/driver.h @@ -21,12 +21,14 @@ #include #include #include +#include /* local includes */ #include namespace Framebuffer { using namespace Genode; + using Area = Capture::Area; class Driver; }; @@ -46,7 +48,7 @@ class Framebuffer::Driver public: - enum Resolutions { BYTES_PER_PIXEL = 2 }; + enum Resolutions { BYTES_PER_PIXEL = 4 }; Driver(Genode::Env &env, Genode::Xml_node config) : _env(env), @@ -66,7 +68,8 @@ class Framebuffer::Driver return true; } - Mode mode() { return Mode { .area = { _width, _height } }; } + Area screen_size() const { return Area { _width, _height }; } + Ipu &ipu() { return _ipu; } }; diff --git a/repos/os/src/drivers/framebuffer/spec/imx53/main.cc b/repos/os/src/drivers/framebuffer/spec/imx53/main.cc index 0a9d644af4..87cfa54947 100644 --- a/repos/os/src/drivers/framebuffer/spec/imx53/main.cc +++ b/repos/os/src/drivers/framebuffer/spec/imx53/main.cc @@ -2,152 +2,78 @@ * \brief Frame-buffer driver for the i.MX53 * \author Nikolay Golikov * \author Stefan Kalkowski + * \author Norman Feske * \date 2012-06-21 */ +/* + * Copyright (C) 2012-2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + /* Genode includes */ #include +#include #include #include -#include #include #include -#include -#include /* local includes */ #include namespace Framebuffer { using namespace Genode; - class Session_component; + struct Main; }; -class Framebuffer::Session_component : - public Genode::Rpc_object +struct Framebuffer::Main { - private: + using Pixel = Capture::Pixel; - /* - * Noncopyable - */ - Session_component(Session_component const &); - Session_component &operator = (Session_component const &); + Env &_env; - Genode::Env &_env; + Attached_rom_dataspace _config { _env, "config" }; - bool _buffered; - Mode _mode; - size_t _size; + Driver _driver { _env, _config.xml() }; - /* dataspace uses a back buffer (if '_buffered' is true) */ - Genode::Dataspace_capability _bb_ds; - void *_bb_addr; + Area const _size = _driver.screen_size(); - /* dataspace of physical frame buffer */ - Genode::Dataspace_capability _fb_ds; - void *_fb_addr; + Attached_ram_dataspace _fb_ds { _env.ram(), _env.rm(), + _size.count()*sizeof(Pixel), WRITE_COMBINED }; - Timer::Connection _timer { _env }; + Capture::Connection _capture { _env }; + Capture::Connection::Screen _captured_screen { _capture, _env.rm(), _size }; - Ipu &_ipu; + Timer::Connection _timer { _env }; - void _refresh_buffered(int x, int y, int w, int h) - { - /* clip specified coordinates against screen boundaries */ - int x2 = min(x + w - 1, (int)_mode.area.w() - 1), - y2 = min(y + h - 1, (int)_mode.area.h() - 1); - int x1 = max(x, 0), - y1 = max(y, 0); - if (x1 > x2 || y1 > y2) return; + Signal_handler
_timer_handler { _env.ep(), *this, &Main::_handle_timer }; - int bypp = _mode.bytes_per_pixel(); - - /* copy pixels from back buffer to physical frame buffer */ - char *src = (char *)_bb_addr + bypp*(_mode.area.w()*y1 + x1), - *dst = (char *)_fb_addr + bypp*(_mode.area.h()*y1 + x1); - - blit(src, bypp*_mode.area.w(), dst, bypp*_mode.area.w(), - bypp*(x2 - x1 + 1), y2 - y1 + 1); - } - - public: - - Session_component(Genode::Env &env, Driver &driver, bool buffered) - : _env(env), - _buffered(buffered), - _mode(driver.mode()), - _size(_mode.bytes_per_pixel()*_mode.area.count()), - _bb_ds(buffered ? _env.ram().alloc(_size) - : Genode::Ram_dataspace_capability()), - _bb_addr(buffered ? (void*)_env.rm().attach(_bb_ds) : 0), - _fb_ds(_env.ram().alloc(_size, WRITE_COMBINED)), - _fb_addr((void*)_env.rm().attach(_fb_ds)), - _ipu(driver.ipu()) - { - if (!driver.init(Dataspace_client(_fb_ds).phys_addr())) { - error("could not initialize display"); - struct Could_not_initialize_display : Exception { }; - throw Could_not_initialize_display(); - } - } - - - /************************************** - ** Framebuffer::session interface ** - **************************************/ - - Dataspace_capability dataspace() override { return _buffered ? _bb_ds : _fb_ds; } - Mode mode() const override { return _mode; } - void mode_sigh(Genode::Signal_context_capability) override { } - - void sync_sigh(Genode::Signal_context_capability sigh) override - { - _timer.sigh(sigh); - _timer.trigger_periodic(10*1000); - } - - void refresh(int x, int y, int w, int h) override - { - if (_buffered) - _refresh_buffered(x, y, w, h); - } - - void overlay(Genode::addr_t phys_base, int x, int y, int alpha) override { - _ipu.overlay(phys_base, x, y, alpha); } -}; - - -static bool config_attribute(Genode::Xml_node node, const char *attr_name) -{ - return node.attribute_value(attr_name, false); -} - - -struct Main -{ - Genode::Env &_env; - Genode::Entrypoint &_ep; - - Genode::Attached_rom_dataspace _config { _env, "config" }; - - Framebuffer::Driver _driver { _env, _config.xml() }; - - Framebuffer::Session_component _fb_session { _env, _driver, - config_attribute(_config.xml(), "buffered") }; - - Genode::Static_root _fb_root { - _ep.manage(_fb_session) }; - - Main(Genode::Env &env) : _env(env), _ep(_env.ep()) + void _handle_timer() { - Genode::log("--- i.MX53 framebuffer driver ---"); + Surface surface(_fb_ds.local_addr(), _size); - _env.parent().announce(_ep.manage(_fb_root)); + _captured_screen.apply_to_surface(surface); + } + + Main(Env &env) : _env(env) + { + log("--- i.MX53 framebuffer driver ---"); + + if (!_driver.init(Dataspace_client(_fb_ds.cap()).phys_addr())) { + error("could not initialize display"); + struct Could_not_initialize_display : Exception { }; + throw Could_not_initialize_display(); + } + + _timer.sigh(_timer_handler); + _timer.trigger_periodic(10*1000); } }; -void Component::construct(Genode::Env &env) { static Main main(env); } +void Component::construct(Genode::Env &env) { static Framebuffer::Main main(env); } diff --git a/repos/os/src/drivers/framebuffer/spec/rpi/main.cc b/repos/os/src/drivers/framebuffer/spec/rpi/main.cc index 961c21962d..89a51886a2 100644 --- a/repos/os/src/drivers/framebuffer/spec/rpi/main.cc +++ b/repos/os/src/drivers/framebuffer/spec/rpi/main.cc @@ -17,131 +17,59 @@ #include #include #include -#include -#include +#include #include #include #include namespace Framebuffer { using namespace Genode; - class Session_component; struct Main; }; -class Framebuffer::Session_component : public Genode::Rpc_object -{ - private: - - size_t const _width; - size_t const _height; - Constructible _bb_mem { }; - Attached_io_mem_dataspace _fb_mem; - Timer::Connection _timer; - - void _refresh_buffered(int x, int y, int w, int h) - { - Mode _mode = mode(); - - /* clip specified coordinates against screen boundaries */ - int x2 = min(x + w - 1, (int)_mode.area.w() - 1), - y2 = min(y + h - 1, (int)_mode.area.h() - 1); - int x1 = max(x, 0), - y1 = max(y, 0); - if (x1 > x2 || y1 > y2) return; - - int bypp = _mode.bytes_per_pixel(); - - /* copy pixels from back buffer to physical frame buffer */ - char *src = _bb_mem->local_addr() + bypp*(_width*y1 + x1), - *dst = _fb_mem.local_addr() + bypp*(_width*y1 + x1); - - blit(src, bypp*_width, dst, bypp*_width, - bypp*(x2 - x1 + 1), y2 - y1 + 1); - } - - public: - - Session_component(Genode::Env &env, addr_t phys_addr, - size_t size, size_t width, size_t height, - bool buffered) - : - _width(width), _height(height), _fb_mem(env, phys_addr, size), - _timer(env) - { - if (buffered) { - _bb_mem.construct(env.ram(), env.rm(), size); - } - } - - /************************************ - ** Framebuffer::Session interface ** - ************************************/ - - Dataspace_capability dataspace() override - { - if (_bb_mem.constructed()) - return _bb_mem->cap(); - else - return _fb_mem.cap(); - } - - Mode mode() const override - { - return Mode { .area = { _width, _height } }; - } - - void mode_sigh(Genode::Signal_context_capability) override { } - - void sync_sigh(Genode::Signal_context_capability sigh) override - { - _timer.sigh(sigh); - _timer.trigger_periodic(10*1000); - } - - void refresh(int x, int y, int w, int h) override - { - if (_bb_mem.constructed()) - _refresh_buffered(x, y, w, h); - } -}; - - -static bool config_buffered(Genode::Xml_node node) -{ - return node.attribute_value("buffered", false); -} - - struct Framebuffer::Main { - Env &_env; - Entrypoint &_ep; + using Area = Capture::Area; + using Pixel = Capture::Pixel; + + Env &_env; Attached_rom_dataspace _config { _env, "config" }; Platform::Connection _platform { _env }; - Platform::Framebuffer_info _fb_info { 1024, 768, 32 }; + Area const _size { 1024, 768 }; - Constructible _fb_session { }; - Constructible> _fb_root { }; + Platform::Framebuffer_info _fb_info { _size.w(), _size.h(), 32 }; - Main(Genode::Env &env) : _env(env), _ep(_env.ep()) + bool const _fb_initialized = ( _platform.setup_framebuffer(_fb_info), true ); + + Attached_io_mem_dataspace _fb_ds { _env, _fb_info.addr, _fb_info.size }; + + Capture::Connection _capture { _env }; + + Capture::Connection::Screen _captured_screen { _capture, _env.rm(), _size }; + + Timer::Connection _timer { _env }; + + Signal_handler
_timer_handler { _env.ep(), *this, &Main::_handle_timer }; + + void _handle_timer() { - log("--- fb_drv started ---"); + Area const phys_size { _fb_info.phys_width, _fb_info.phys_height }; - _platform.setup_framebuffer(_fb_info); + Surface surface(_fb_ds.local_addr(), phys_size); - _fb_session.construct(_env, _fb_info.addr, _fb_info.size, - _fb_info.phys_width, _fb_info.phys_height, - config_buffered(_config.xml())); + _captured_screen.apply_to_surface(surface); + } - _fb_root.construct(_ep.manage(*_fb_session)); + Main(Genode::Env &env) : _env(env) + { + log("--- rpi_fb_drv started ---"); - /* announce service */ - env.parent().announce(_ep.manage(*_fb_root)); + _timer.sigh(_timer_handler); + _timer.trigger_periodic(10*1000); } }; diff --git a/repos/os/src/drivers/framebuffer/spec/sdl/main.cc b/repos/os/src/drivers/framebuffer/spec/sdl/main.cc index b1b5e3864e..3cf8575e06 100644 --- a/repos/os/src/drivers/framebuffer/spec/sdl/main.cc +++ b/repos/os/src/drivers/framebuffer/spec/sdl/main.cc @@ -15,10 +15,9 @@ /* Genode includes */ #include #include -#include -#include +#include +#include #include -#include /* Linux includes */ #include @@ -26,12 +25,6 @@ /* local includes */ #include "convert_keycode.h" -namespace Framebuffer { - class Session_component; - using namespace Genode; -} - - namespace Fb_sdl { class Main; using namespace Genode; @@ -44,140 +37,6 @@ struct Sdl_videodriver_not_supported : Genode::Exception { }; struct Sdl_setvideomode_failed : Genode::Exception { }; -class Framebuffer::Session_component : public Rpc_object -{ - private: - - /* - * Noncopyable - */ - Session_component(Session_component const &); - Session_component &operator = (Session_component const &); - - Env &_env; - - Mode _next_mode; - Mode mutable _requested_mode = _next_mode; - Mode _mode = _next_mode; - - SDL_Surface *_screen { nullptr }; - - Constructible _fb_ds { }; - - Signal_context_capability _mode_sigh { }; - Signal_context_capability _sync_sigh { }; - - public: - - void submit_sync() - { - if (_sync_sigh.valid()) - Signal_transmitter(_sync_sigh).submit(); - } - - void submit_mode_change(Mode next_mode) - { - _next_mode = next_mode; - - if (_mode_sigh.valid()) - Signal_transmitter(_mode_sigh).submit(); - } - - /** - * Constructor - */ - Session_component(Env &env, Framebuffer::Mode next_mode) - : - _env(env), _next_mode(next_mode) - { } - - Dataspace_capability dataspace() override - { - unsigned const bpp = _requested_mode.bytes_per_pixel(); - unsigned const flags = SDL_SWSURFACE | SDL_RESIZABLE; - unsigned const w = _requested_mode.area.w(); - unsigned const h = _requested_mode.area.h(); - - if (SDL_VideoModeOK(w, h, bpp*8, flags)) - _screen = SDL_SetVideoMode(w, h, bpp*8, flags); - - if (!_screen) { - error("SDL_SetVideoMode failed (", Genode::Cstring(SDL_GetError()), ")"); - throw Sdl_setvideomode_failed(); - } - - /* - * Preserve content of old dataspace in new SDL screen to reduce - * flickering during resize. - * - * Note that flickering cannot fully be avoided because the host - * window is immediately cleared by 'SDL_SetVideoMode'. - */ - refresh(0, 0, w, h); - - _mode = _requested_mode; - - /* - * Allocate new dataspace, and initialize with the original pixels. - */ - _fb_ds.construct(_env.ram(), _env.rm(), w*h*bpp); - - blit(_screen->pixels, _screen->pitch, _fb_ds->local_addr(), bpp*w, - min(w, (unsigned)_screen->w)*bpp, - min(h, (unsigned)_screen->h)); - - return _fb_ds->cap(); - } - - Mode mode() const override - { - _requested_mode = _next_mode; - return _requested_mode; - } - - void mode_sigh(Signal_context_capability sigh) override - { - _mode_sigh = sigh; - } - - void sync_sigh(Signal_context_capability sigh) override - { - _sync_sigh = sigh; - } - - void refresh(int x, int y, int w, int h) override - { - if (!_fb_ds.constructed()) - return; - - /* clip refresh area to screen boundaries */ - int const x1 = max(x, 0); - int const y1 = max(y, 0); - int const x2 = min(x + w - 1, min((int)_mode.area.w(), _screen->w) - 1); - int const y2 = min(y + h - 1, min((int)_mode.area.h(), _screen->h) - 1); - - if (x1 > x2 || y1 > y2) - return; - - /* blit pixels from framebuffer dataspace to SDL screen */ - unsigned const bpp = _mode.bytes_per_pixel(); - - char const * const src_base = _fb_ds->local_addr(); - unsigned const src_pitch = bpp*_mode.area.w(); - char const * const src = src_base + y1*src_pitch + bpp*x1; - - unsigned const dst_pitch = _screen->pitch; - char * const dst_base = (char *)_screen->pixels; - char * const dst = dst_base + y1*dst_pitch + bpp*x1; - - blit(src, src_pitch, dst, dst_pitch, bpp*(x2 - x1 + 1), y2 - y1 + 1); - - /* flush pixels in sdl window */ - SDL_UpdateRect(_screen, x1, y1, x2 - x1 + 1, y2 - y1 + 1); - } -}; - - struct Fb_sdl::Main { Env &_env; @@ -185,34 +44,15 @@ struct Fb_sdl::Main Attached_rom_dataspace _config { _env, "config" }; Timer::Connection _timer { _env }; + Event::Connection _event { _env }; - unsigned const _fb_width = _config.xml().attribute_value("width", 1024UL); - unsigned const _fb_height = _config.xml().attribute_value("height", 768UL); + using Area = Capture::Area; + using Point = Capture::Area; + using Pixel = Capture::Pixel; + using Affected_rects = Capture::Session::Affected_rects; + using Event_batch = Event::Session_client::Batch; - Framebuffer::Mode _fb_mode { .area = { _fb_width, _fb_height } }; - - Framebuffer::Session_component _fb_session { _env, _fb_mode }; - - Static_root _fb_root { _env.ep().manage(_fb_session) }; - - Input::Session_component _input_session { _env, _env.ram() }; - Input::Root_component _input_root { _env.ep().rpc_ep(), _input_session }; - - Signal_handler
_timer_handler { - _env.ep(), *this, &Main::_handle_timer }; - - int _mx = 0, _my = 0; - - void _handle_sdl_event(SDL_Event const &event); - void _handle_sdl_events(); - - void _handle_timer() - { - _handle_sdl_events(); - _fb_session.submit_sync(); - } - - Main(Env &env) : _env(env) + void _init_sdl() { /* * Initialize libSDL window @@ -234,9 +74,103 @@ struct Fb_sdl::Main } SDL_ShowCursor(0); + } - _env.parent().announce(env.ep().manage(_fb_root)); - _env.parent().announce(env.ep().manage(_input_root)); + bool const _sdl_initialized = ( _init_sdl(), true ); + + struct Sdl_screen + { + Area const size; + + SDL_Surface &_sdl_surface = _init_sdl_surface(); + + SDL_Surface &_init_sdl_surface() + { + unsigned const bpp = 32; + unsigned const flags = SDL_SWSURFACE | SDL_RESIZABLE; + + SDL_Surface *surface_ptr = nullptr; + + if (SDL_VideoModeOK(size.w(), size.h(), bpp, flags)) + surface_ptr = SDL_SetVideoMode(size.w(), size.h(), bpp, flags); + + if (!surface_ptr) { + error("SDL_SetVideoMode failed (", Genode::Cstring(SDL_GetError()), ")"); + throw Sdl_setvideomode_failed(); + } + return *surface_ptr; + } + + Sdl_screen(Area size) : size(size) { } + + template + void with_surface(FN const &fn) + { + Surface surface { (Pixel *)_sdl_surface.pixels, size }; + fn(surface); + } + + void flush(Capture::Rect rect) + { + SDL_UpdateRect(&_sdl_surface, rect.x1(), rect.y1(), rect.w(), rect.h()); + } + }; + + Constructible _sdl_screen { }; + + Capture::Connection _capture { _env }; + + Constructible _captured_screen { }; + + Signal_handler
_timer_handler { + _env.ep(), *this, &Main::_handle_timer }; + + int _mx = 0, _my = 0; + + void _handle_sdl_event(Event_batch &, SDL_Event const &); + void _handle_sdl_events(); + + void _update_sdl_screen_from_capture() + { + Affected_rects const affected = _capture.capture_at(Capture::Point(0, 0)); + + _sdl_screen->with_surface([&] (Surface &surface) { + + _captured_screen->with_texture([&] (Texture const &texture) { + + affected.for_each_rect([&] (Capture::Rect const rect) { + + surface.clip(rect); + + Blit_painter::paint(surface, texture, Capture::Point(0, 0)); + }); + }); + }); + + /* flush pixels in SDL window */ + affected.for_each_rect([&] (Capture::Rect const rect) { + _sdl_screen->flush(rect); }); + } + + void _handle_timer() + { + _handle_sdl_events(); + + _update_sdl_screen_from_capture(); + } + + void _resize(Area size) + { + + _sdl_screen.construct(size); + _captured_screen.construct(_capture, _env.rm(), size); + _update_sdl_screen_from_capture(); + } + + Main(Env &env) : _env(env) + { + _resize(Area(_config.xml().attribute_value("width", 1024U), + _config.xml().attribute_value("height", 768U))); _timer.sigh(_timer_handler); _timer.trigger_periodic(100000000 / 5994); /* 59.94Hz */ @@ -244,7 +178,7 @@ struct Fb_sdl::Main }; -void Fb_sdl::Main::_handle_sdl_event(SDL_Event const &event) +void Fb_sdl::Main::_handle_sdl_event(Event_batch &batch, SDL_Event const &event) { using namespace Input; @@ -255,9 +189,7 @@ void Fb_sdl::Main::_handle_sdl_event(SDL_Event const &event) return; } - Framebuffer::Mode const mode { .area = { (unsigned)event.resize.w, - (unsigned)event.resize.h } }; - _fb_session.submit_mode_change(mode); + _resize(Area((unsigned)event.resize.w, (unsigned)event.resize.h)); return; } @@ -270,7 +202,7 @@ void Fb_sdl::Main::_handle_sdl_event(SDL_Event const &event) if (ox == _mx && oy == _my) return; - _input_session.submit(Absolute_motion{_mx, _my}); + batch.submit(Absolute_motion{_mx, _my}); return; } @@ -304,18 +236,18 @@ void Fb_sdl::Main::_handle_sdl_event(SDL_Event const &event) /* ignore */ return; - _input_session.submit(Release{keycode}); + batch.submit(Release{keycode}); return; case SDL_KEYDOWN: case SDL_MOUSEBUTTONDOWN: if (event.button.button == SDL_BUTTON_WHEELUP) - _input_session.submit(Wheel{0, 1}); + batch.submit(Wheel{0, 1}); else if (event.button.button == SDL_BUTTON_WHEELDOWN) - _input_session.submit(Wheel{0, -1}); + batch.submit(Wheel{0, -1}); else - _input_session.submit(Press{keycode}); + batch.submit(Press{keycode}); return; default: @@ -327,8 +259,12 @@ void Fb_sdl::Main::_handle_sdl_event(SDL_Event const &event) void Fb_sdl::Main::_handle_sdl_events() { SDL_Event event { }; - while (SDL_PollEvent(&event)) - _handle_sdl_event(event); + + _event.with_batch([&] (Event_batch &batch) { + + while (SDL_PollEvent(&event)) + _handle_sdl_event(batch, event); + }); } diff --git a/repos/os/src/test/framebuffer/main.cc b/repos/os/src/test/framebuffer/main.cc index e60c6a7327..890ac3b31b 100644 --- a/repos/os/src/test/framebuffer/main.cc +++ b/repos/os/src/test/framebuffer/main.cc @@ -1,13 +1,14 @@ /* - * \brief Basic test for framebuffer session + * \brief Basic test for framebuffer drivers * \author Martin Stein * \author Christian Helmuth * \author Stefan Kalkowski + * \author Norman Feske * \date 2012-01-09 */ /* - * Copyright (C) 2012-2017 Genode Labs GmbH + * Copyright (C) 2012-2020 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. @@ -16,71 +17,107 @@ /* Genode includes */ #include #include -#include -#include -#include -#include +#include +#include +#include #include +namespace Test { -using Area = Genode::Surface_base::Area; -using Pixel = Genode::Pixel_rgb888; + using namespace Genode; -class Test_environment + using Area = Capture::Area; + using Point = Capture::Point; + using Pixel = Capture::Pixel; + + struct Capture_session; + class Main; +} + + +struct Test::Capture_session : Rpc_object +{ + Env &_env; + + Pixel const BLACK = { 0, 0, 0 }; + Pixel const BLUE = { 0, 0, 255 }; + Pixel const GREEN = { 0, 255, 0 }; + Pixel const RED = { 255, 0, 0 }; + Pixel const WHITE = { 255, 255, 255 }; + + enum State { STRIPES, ALL_BLUE, ALL_GREEN, ALL_RED, COLORED }; + + Area _size { 0, 0 }; + + Constructible _ds { }; + + State _state = STRIPES; + + unsigned long _sync_cnt = 0; + + enum { FRAME_CNT = 200 }; + + void _draw(); + + void _draw_frame(Pixel *, Pixel, Area); + + Capture_session(Env &env) : _env(env) { } + + + /******************************** + ** Capture::Session interface ** + ********************************/ + + Area screen_size() const override { return _size; } + + void screen_size_sigh(Signal_context_capability) override { } + + void buffer(Area size) override + { + _ds.construct(_env.ram(), _env.rm(), buffer_bytes(size)); + _size = size; + _draw(); + } + + Dataspace_capability dataspace() override + { + return _ds.constructed() ? _ds->cap() : Ram_dataspace_capability(); + } + + Affected_rects capture_at(Point) override + { + Affected_rects affected { }; + + if (_sync_cnt++ % FRAME_CNT == 0) { + _draw(); + affected.rects[0] = Rect(Point(0, 0), _size); + } + + return affected; + } +}; + + +class Test::Main { private: - using Ds = Genode::Constructible; + Env &_env; - Pixel const BLACK = { 0, 0, 0 }; - Pixel const BLUE = { 0, 0, 255 }; - Pixel const GREEN = { 0, 255, 0 }; - Pixel const RED = { 255, 0, 0 }; - Pixel const WHITE = { 255, 255, 255 }; + Capture_session _capture_session { _env }; - enum State { STRIPES, ALL_BLUE, ALL_GREEN, ALL_RED, COLORED }; - - Genode::Env &_env; - - Framebuffer::Mode _mode { }; - Framebuffer::Connection _fb { _env, _mode }; - Ds _fb_ds { }; - Genode::Signal_handler _mode_sigh; - Genode::Signal_handler _sync_sigh; - unsigned long _sync_cnt = 0; - State _state = STRIPES; - - enum { FRAME_CNT = 200 }; - - void _draw(); - void _mode_handle(); - - void _sync_handle() { - if (_sync_cnt++ % FRAME_CNT == 0) _draw(); } - - void _draw_frame(Pixel *, Pixel, Area); - - Genode::size_t _fb_bpp() { return _mode.bytes_per_pixel(); } - Genode::size_t _fb_size() { return _fb_ds->size(); } - Genode::addr_t _fb_base() { - return (Genode::addr_t) _fb_ds->local_addr(); } + Static_root _capture_root { _env.ep().manage(_capture_session) }; public: - Test_environment(Genode::Env &env) - : - _env(env), - _mode_sigh(_env.ep(), *this, &Test_environment::_mode_handle), - _sync_sigh(_env.ep(), *this, &Test_environment::_sync_handle) + Main(Env &env) : _env(env) { - _fb.mode_sigh(_mode_sigh); - _fb.sync_sigh(_sync_sigh); - _mode_handle(); + _env.parent().announce(env.ep().manage(_capture_root)); } }; -void Test_environment::_draw_frame(Pixel *p, Pixel c, Area area) +void Test::Capture_session::_draw_frame(Pixel *p, Pixel c, Area area) { unsigned const w = area.w(), h = area.h(); @@ -94,91 +131,81 @@ void Test_environment::_draw_frame(Pixel *p, Pixel c, Area area) } -void Test_environment::_draw() +void Test::Capture_session::_draw() { - using namespace Genode; + if (!_ds.constructed()) + return; + + addr_t const num_pixels = _size.count(); + + Pixel * const fb_base = _ds->local_addr(); switch(_state) { case STRIPES: { - Genode::log("black & white stripes"); - addr_t const stripe_width = _mode.area.w() / 4; + log("black & white stripes"); + addr_t const stripe_width = _size.w() / 4; addr_t stripe_o = 0; bool stripe = 0; - for (addr_t o = 0; o < _fb_size(); o += _fb_bpp()) { + for (addr_t o = 0; o < num_pixels; o++) { stripe_o++; if (stripe_o == stripe_width) { stripe_o = 0; stripe = !stripe; } - *(Pixel *)(_fb_base() + o) = stripe ? BLACK : WHITE; + fb_base[o] = stripe ? BLACK : WHITE; } - _draw_frame((Pixel *)_fb_base(), RED, _mode.area); + _draw_frame(fb_base, RED, _size); _state = ALL_BLUE; break; } case ALL_BLUE: { - Genode::log("blue"); - for (addr_t o = 0; o < _fb_size(); o += _fb_bpp()) - *(Pixel *)(_fb_base() + o) = BLUE; + log("blue"); + for (addr_t o = 0; o < num_pixels; o++) + fb_base[o] = BLUE; - _draw_frame((Pixel *)_fb_base(), RED, _mode.area); + _draw_frame(fb_base, RED, _size); _state = ALL_GREEN; break; } case ALL_GREEN: { - Genode::log("green"); - for (addr_t o = 0; o < _fb_size(); o += _fb_bpp()) - *(Pixel *)(_fb_base() + o) = GREEN; + log("green"); + for (addr_t o = 0; o < num_pixels; o++) + fb_base[o] = GREEN; - _draw_frame((Pixel *)_fb_base(), RED, _mode.area); + _draw_frame(fb_base, RED, _size); _state = ALL_RED; break; } case ALL_RED: { - Genode::log("red"); - for (addr_t o = 0; o < _fb_size(); o += _fb_bpp()) - *(Pixel *)(_fb_base() + o) = RED; + log("red"); + for (addr_t o = 0; o < num_pixels; o++) + fb_base[o] = RED; - _draw_frame((Pixel *)_fb_base(), WHITE, _mode.area); + _draw_frame(fb_base, WHITE, _size); _state = COLORED; break; } case COLORED: { - Genode::log("all colors mixed"); + log("all colors mixed"); unsigned i = 0; - for (addr_t o = 0; o < _fb_size(); o += _fb_bpp(), i++) - *(Pixel *)(_fb_base() + o) = Pixel(i>>16, i>>8, i); + for (addr_t o = 0; o < num_pixels; o++, i++) + fb_base[o] = Pixel(i>>16, i>>8, i); - _draw_frame((Pixel *)_fb_base(), WHITE, _mode.area); + _draw_frame(fb_base, WHITE, _size); _state = STRIPES; } }; - _fb.refresh(0, 0, _mode.area.w(), _mode.area.h()); -} - - -void Test_environment::_mode_handle() -{ - _mode = _fb.mode(); - if (_fb_ds.constructed()) - _fb_ds.destruct(); - - _fb_ds.construct(_env.rm(), _fb.dataspace()); - - Genode::log("framebuffer is ", _mode); - - _draw(); } void Component::construct(Genode::Env &env) { Genode::log("--- Test framebuffer ---"); - static Test_environment te(env); + static Test::Main main(env); } diff --git a/repos/ports/run/bash.run b/repos/ports/run/bash.run index 1c2de156ed..ca085052fe 100644 --- a/repos/ports/run/bash.run +++ b/repos/ports/run/bash.run @@ -11,6 +11,8 @@ import_from_depot [depot_user]/src/[base_src] \ [depot_user]/src/coreutils \ [depot_user]/src/vfs \ [depot_user]/src/vfs_pipe \ + [depot_user]/src/nitpicker \ + [depot_user]/src/gui_fb \ [depot_user]/src/fs_rom # write default vimrc file @@ -53,12 +55,35 @@ install_config { - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -66,6 +91,8 @@ install_config { + + @@ -125,6 +152,10 @@ install_config { } +set fd [open [run_dir]/genode/focus w] +puts $fd " \" domain=\"default\"/>" +close $fd + build { lib/ld test/fork test/execve } build_boot_image { ld.lib.so libc.lib.so libm.lib.so vfs.lib.so posix.lib.so } diff --git a/repos/ports/run/debug_nitpicker.run b/repos/ports/run/debug_nitpicker.run index 0f51e251df..1f2370ed47 100644 --- a/repos/ports/run/debug_nitpicker.run +++ b/repos/ports/run/debug_nitpicker.run @@ -70,20 +70,20 @@ install_config { - + + - - - + - + - + + - - - - + + + + } append_if [expr $use_framebuffer && [have_include "power_on/qemu"]] config { } @@ -408,7 +408,8 @@ append_if $use_usb config { append config { - + + @@ -430,16 +431,16 @@ append config { - - - + + - + + diff --git a/repos/ports/run/vbox5_genode_usb_hid.run b/repos/ports/run/vbox5_genode_usb_hid.run index 0bdb1cdb5f..99ee94fe13 100644 --- a/repos/ports/run/vbox5_genode_usb_hid.run +++ b/repos/ports/run/vbox5_genode_usb_hid.run @@ -146,19 +146,18 @@ append config { - - + - + - - + + diff --git a/repos/ports/run/vbox_share.inc b/repos/ports/run/vbox_share.inc index c8ccd6d5a1..1422479788 100644 --- a/repos/ports/run/vbox_share.inc +++ b/repos/ports/run/vbox_share.inc @@ -278,14 +278,14 @@ append config_of_app { - + - - + + diff --git a/repos/ports/run/vbox_win.inc b/repos/ports/run/vbox_win.inc index 553c969eff..348b1a0f36 100644 --- a/repos/ports/run/vbox_win.inc +++ b/repos/ports/run/vbox_win.inc @@ -125,9 +125,8 @@ append config_of_app { - + - @@ -182,7 +181,8 @@ append config_of_app { - + + @@ -198,7 +198,8 @@ append config_of_app { append_if [expr !$use_rumpfs] config_of_app { - + + diff --git a/repos/ports/run/vim.run b/repos/ports/run/vim.run index f591a256a0..eeef24f0d4 100644 --- a/repos/ports/run/vim.run +++ b/repos/ports/run/vim.run @@ -46,12 +46,11 @@ install_config { - + + - - - + @@ -66,8 +65,9 @@ install_config { - - + + + @@ -77,9 +77,8 @@ install_config { - - - + + diff --git a/repos/ports/run/virtualbox.run b/repos/ports/run/virtualbox.run index 511e2df5f5..35cbda963c 100644 --- a/repos/ports/run/virtualbox.run +++ b/repos/ports/run/virtualbox.run @@ -102,8 +102,7 @@ append_if [expr $use_usb] config { append_if [have_spec framebuffer] config { - - } + } append_if [expr [have_spec framebuffer] && [have_include power_on/qemu]] config { } append_if [expr [have_spec framebuffer] && [have_include power_on/qemu]] config { @@ -114,10 +113,7 @@ append_if [have_spec framebuffer] config { append_if [have_spec sdl] config { - - - - + } append_if [have_spec x86] config { @@ -169,9 +165,8 @@ append config { - + - } append_if [expr $use_ps2] config { @@ -182,7 +177,9 @@ append_if [expr $use_usb] config { append config { - + + + diff --git a/repos/ports/run/virtualbox_auto.inc b/repos/ports/run/virtualbox_auto.inc index 2c971cb09b..33ce58b735 100644 --- a/repos/ports/run/virtualbox_auto.inc +++ b/repos/ports/run/virtualbox_auto.inc @@ -352,8 +352,7 @@ append_if [have_spec framebuffer] config { - - + } append_if [have_spec x86] config {