From f147a1220e5c9e11357ec60de108f62d0f7ba44c Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Mon, 26 Aug 2024 17:02:28 +0200 Subject: [PATCH] intel/display: make effective use of PSR - only mark framebuffer dirty if necessary -> gives the hardware chance to save longer power - remove extra timer connection on Genode component side -> use Linux time primitives Issue #5339 --- .../src/driver/framebuffer/intel/pc/lx_i915.h | 1 + .../src/driver/framebuffer/intel/pc/lx_user.c | 8 ++- .../src/driver/framebuffer/intel/pc/main.cc | 50 +++++++++++-------- 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/repos/pc/src/driver/framebuffer/intel/pc/lx_i915.h b/repos/pc/src/driver/framebuffer/intel/pc/lx_i915.h index 2ae68b1228..3eb8eb5444 100644 --- a/repos/pc/src/driver/framebuffer/intel/pc/lx_i915.h +++ b/repos/pc/src/driver/framebuffer/intel/pc/lx_i915.h @@ -32,6 +32,7 @@ struct genode_mode { char name[32]; }; +int lx_emul_i915_blit(void); void lx_emul_i915_report(void * genode_xml); void lx_emul_i915_hotplug_connector(void); void lx_emul_i915_report_connector(void * lx_data, void * genode_xml, diff --git a/repos/pc/src/driver/framebuffer/intel/pc/lx_user.c b/repos/pc/src/driver/framebuffer/intel/pc/lx_user.c index bae52778fe..4830133ff1 100644 --- a/repos/pc/src/driver/framebuffer/intel/pc/lx_user.c +++ b/repos/pc/src/driver/framebuffer/intel/pc/lx_user.c @@ -504,8 +504,12 @@ void framebuffer_dirty(void) static int update_content(void *) { while (true) { - framebuffer_dirty(); - lx_emul_task_schedule(true /* block task */); + + if (lx_emul_i915_blit()) + framebuffer_dirty(); + + /* schedule_timeout(jiffes) or hrtimer or msleep */ + msleep(20); } return 0; diff --git a/repos/pc/src/driver/framebuffer/intel/pc/main.cc b/repos/pc/src/driver/framebuffer/intel/pc/main.cc index 841cd5d9ee..aca7b0fbba 100644 --- a/repos/pc/src/driver/framebuffer/intel/pc/main.cc +++ b/repos/pc/src/driver/framebuffer/intel/pc/main.cc @@ -13,7 +13,6 @@ #include #include -#include #include #include #include @@ -33,7 +32,6 @@ extern "C" { extern struct task_struct * lx_user_task; -extern struct task_struct * lx_update_task; namespace Framebuffer { @@ -47,15 +45,12 @@ struct Framebuffer::Driver using Attached_rom_system = Constructible; Env &env; - Timer::Connection timer { env }; Attached_rom_dataspace config { env, "config" }; Attached_rom_system system { }; Expanding_reporter reporter { env, "connectors", "connectors" }; Signal_handler config_handler { env.ep(), *this, &Driver::config_update }; - Signal_handler timer_handler { env.ep(), *this, - &Driver::handle_timer }; Signal_handler scheduler_handler { env.ep(), *this, &Driver::handle_scheduler }; Signal_handler system_handler { env.ep(), *this, @@ -84,17 +79,29 @@ struct Framebuffer::Driver public: - void paint() + bool paint() { using Pixel = Capture::Pixel; - Surface surface((Pixel*)_base, _size_phys); - _captured_screen.apply_to_surface(surface); - if (!lx_update_task) - return; + bool dirty = false; - lx_emul_task_unblock(lx_update_task); - Lx_kit::env().scheduler.execute(); + _captured_screen.with_texture([&] (Texture const &texture) { + + auto const affected = _capture.capture_at(Capture::Point(0, 0)); + + affected.for_each_rect([&] (Capture::Rect const rect) { + + Surface surface((Pixel*)_base, _size_phys); + + surface.clip(rect); + + Blit_painter::paint(surface, texture, Capture::Point(0, 0)); + + dirty = true; + }); + }); + + return dirty; } Fb(Env & env, void * base, Capture::Area size, @@ -121,11 +128,6 @@ struct Framebuffer::Driver void generate_report(); void lookup_config(char const *, struct genode_mode &mode); - void handle_timer() - { - if (fb.constructed()) { fb->paint(); } - } - void handle_scheduler() { Lx_kit::env().scheduler.execute(); @@ -164,9 +166,6 @@ struct Framebuffer::Driver log("--- Intel framebuffer driver started ---"); lx_emul_start_kernel(nullptr); - - timer.sigh(timer_handler); - timer.trigger_periodic(20*1000); } bool apply_config_on_hotplug() const @@ -467,6 +466,17 @@ void lx_emul_i915_report_modes(void * genode_xml, struct genode_mode *mode) } +int lx_emul_i915_blit() +{ + auto &drv = driver(Lx_kit::env().env); + + if (!drv.fb.constructed()) + return false; + + return drv.fb->paint(); +} + + void lx_emul_i915_connector_config(char * name, struct genode_mode * mode) { if (!mode || !name)