From 795a817a339f8c304558476e2c79181ccb453858 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Fri, 26 Jun 2020 20:06:20 +0200 Subject: [PATCH] nitpicker: remove dirty_rect state from view stack In the presence of potentially multiple output back ends, this dirty_rect state must be maintained individually per back end. Instead of storing the dirty_rect as view-stack member, the view stack now calls a new 'Damage::mark_as_damaged' interface, which allows nitpicker to propagate this information to multiple back ends. Unfortunately, the patch must remove the per-view dirty_rect state. Issue #3812 --- repos/os/src/server/nitpicker/main.cc | 49 ++++++++++++------- repos/os/src/server/nitpicker/view.h | 21 --------- repos/os/src/server/nitpicker/view_stack.cc | 12 ++--- repos/os/src/server/nitpicker/view_stack.h | 52 ++++++--------------- 4 files changed, 52 insertions(+), 82 deletions(-) diff --git a/repos/os/src/server/nitpicker/main.cc b/repos/os/src/server/nitpicker/main.cc index c66a879574..2ce3d1dd10 100644 --- a/repos/os/src/server/nitpicker/main.cc +++ b/repos/os/src/server/nitpicker/main.cc @@ -22,6 +22,7 @@ #include #include #include +#include /* local includes */ #include "types.h" @@ -195,7 +196,7 @@ class Nitpicker::Gui_root : public Root_component, }; -struct Nitpicker::Main : Focus_updater +struct Nitpicker::Main : Focus_updater, View_stack::Damage { Env &_env; @@ -225,15 +226,33 @@ struct Nitpicker::Main : Focus_updater Area size = screen.size(); + typedef Genode::Dirty_rect Dirty_rect; + + Dirty_rect dirty_rect { }; + /** * Constructor */ Framebuffer_screen(Region_map &rm, Framebuffer::Session &fb) - : framebuffer(fb), fb_ds(rm, framebuffer.dataspace()) { } + : + framebuffer(fb), fb_ds(rm, framebuffer.dataspace()) + { + dirty_rect.mark_as_dirty(Rect(Point(0, 0), size)); + } }; Reconstructible _fb_screen = { _env.rm(), _framebuffer }; + /** + * View_stack::Damage interface + */ + void mark_as_damaged(Rect rect) override + { + if (_fb_screen.constructed()) { + _fb_screen->dirty_rect.mark_as_dirty(rect); + } + } + Point _initial_pointer_pos() { Area const scr_size = _fb_screen->screen.size(); @@ -266,7 +285,7 @@ struct Nitpicker::Main : Focus_updater Tff_font const _font { _binary_default_tff_start, _glyph_buffer }; Focus _focus { }; - View_stack _view_stack { _fb_screen->screen.size(), _focus, _font }; + View_stack _view_stack { _fb_screen->screen.size(), _focus, _font, *this }; User_state _user_state { _focus, _global_keys, _view_stack, _initial_pointer_pos() }; View_owner _global_view_owner { }; @@ -361,16 +380,6 @@ struct Nitpicker::Main : Focus_updater */ bool _motion_activity = false; - /** - * Perform redraw and flush pixels to the framebuffer - */ - void _draw_and_flush() - { - _view_stack.draw(_fb_screen->screen).flush([&] (Rect const &rect) { - _framebuffer.refresh(rect.x1(), rect.y1(), - rect.w(), rect.h()); }); - } - Main(Env &env) : _env(env) { _view_stack.default_background(_builtin_background); @@ -471,13 +480,19 @@ void Nitpicker::Main::_handle_input() if (result.motion_activity) _view_stack.geometry(_pointer_origin, Rect(_user_state.pointer_pos(), Area())); - /* perform redraw and flush pixels to the framebuffer */ - _view_stack.draw(_fb_screen->screen).flush([&] (Rect const &rect) { + /* perform redraw */ + { + /* call 'Dirty_rect::flush' on a copy to preserve the state */ + Dirty_rect dirty_rect = _fb_screen->dirty_rect; + dirty_rect.flush([&] (Rect const &rect) { + _view_stack.draw(_fb_screen->screen, rect); }); + } + + /* flush pixels to the framebuffer, reset dirty_rect */ + _fb_screen->dirty_rect.flush([&] (Rect const &rect) { _framebuffer.refresh(rect.x1(), rect.y1(), rect.w(), rect.h()); }); - _view_stack.mark_all_views_as_clean(); - /* deliver framebuffer synchronization events */ for (Gui_session *s = _session_list.first(); s; s = s->next()) s->submit_sync(); diff --git a/repos/os/src/server/nitpicker/view.h b/repos/os/src/server/nitpicker/view.h index 09fffa6c3e..25fe2f711c 100644 --- a/repos/os/src/server/nitpicker/view.h +++ b/repos/os/src/server/nitpicker/view.h @@ -17,7 +17,6 @@ /* Genode includes */ #include #include -#include #include #include @@ -30,8 +29,6 @@ namespace Nitpicker { class Buffer; class Focus; - typedef Dirty_rect Dirty_rect; - /* * For each buffer, there is a list of views that belong to this buffer. */ @@ -104,7 +101,6 @@ class Nitpicker::View : private Same_buffer_list_elem, Point _buffer_off { }; /* offset to the visible buffer area */ View_owner &_owner; Title _title { "" }; - Dirty_rect _dirty_rect { }; List _children { }; @@ -274,23 +270,6 @@ class Nitpicker::View : private Same_buffer_list_elem, * Return true if input at screen position 'p' refers to the view */ bool input_response_at(Point p) const; - - /** - * Mark part of view as dirty - * - * \param rect dirty rectangle in absolute coordinates - */ - void mark_as_dirty(Rect rect) { _dirty_rect.mark_as_dirty(rect); } - - /** - * Return dirty-rectangle information - */ - Dirty_rect dirty_rect() const { return _dirty_rect; } - - /** - * Reset dirty rectangle - */ - void mark_as_clean() { _dirty_rect = Dirty_rect(); } }; #endif /* _VIEW_H_ */ diff --git a/repos/os/src/server/nitpicker/view_stack.cc b/repos/os/src/server/nitpicker/view_stack.cc index 943a1bdae0..e385029b3e 100644 --- a/repos/os/src/server/nitpicker/view_stack.cc +++ b/repos/os/src/server/nitpicker/view_stack.cc @@ -190,9 +190,8 @@ void View_stack::draw_rec(Canvas_base &canvas, Font const &font, if (next && left.valid()) draw_rec(canvas, font, next, left); /* draw current view */ - view->dirty_rect().flush([&] (Rect const &dirty_rect) { - - Clip_guard clip_guard(canvas, Rect::intersect(clipped, dirty_rect)); + { + Clip_guard clip_guard(canvas, clipped); /* draw background if view is transparent */ if (view->uses_alpha()) @@ -200,7 +199,7 @@ void View_stack::draw_rec(Canvas_base &canvas, Font const &font, view->frame(canvas, _focus); view->draw(canvas, font, _focus); - }); + } /* draw areas at the bottom/right of the current view */ if (next && right.valid()) draw_rec(canvas, font, next, right); @@ -213,8 +212,7 @@ void View_stack::refresh_view(View &view, Rect const rect) /* rectangle constrained to view geometry */ Rect const view_rect = Rect::intersect(rect, _outline(view)); - for (View *v = _first_view(); v; v = v->view_stack_next()) - _mark_view_as_dirty(*v, view_rect); + _damage.mark_as_damaged(view_rect); view.for_each_child([&] (View &child) { refresh_view(child, rect); }); } @@ -286,7 +284,7 @@ void View_stack::title(View &view, const char *title) view.title(_font, title); _place_labels(view.abs_geometry()); - _mark_view_as_dirty(view, _outline(view)); + _damage.mark_as_damaged(_outline(view)); } diff --git a/repos/os/src/server/nitpicker/view_stack.h b/repos/os/src/server/nitpicker/view_stack.h index c9d50ae771..7921cd2476 100644 --- a/repos/os/src/server/nitpicker/view_stack.h +++ b/repos/os/src/server/nitpicker/view_stack.h @@ -23,6 +23,13 @@ namespace Nitpicker { class View_stack; } class Nitpicker::View_stack { + public: + + struct Damage : Interface, Noncopyable + { + virtual void mark_as_damaged(Rect) = 0; + }; + private: Area _size; @@ -30,7 +37,7 @@ class Nitpicker::View_stack Font const &_font; List _views { }; View *_default_background = nullptr; - Dirty_rect mutable _dirty_rect { }; + Damage &_damage; /** * Return outline geometry of a view @@ -79,27 +86,15 @@ class Nitpicker::View_stack template VIEW *_next_view(VIEW &view) const; - /** - * Schedule 'rect' to be redrawn - */ - void _mark_view_as_dirty(View &view, Rect rect) - { - _dirty_rect.mark_as_dirty(rect); - - view.mark_as_dirty(rect); - } - public: /** * Constructor */ - View_stack(Area size, Focus &focus, Font const &font) + View_stack(Area size, Focus &focus, Font const &font, Damage &damage) : - _size(size), _focus(focus), _font(font) - { - _dirty_rect.mark_as_dirty(Rect(Point(0, 0), _size)); - } + _size(size), _focus(focus), _font(font), _damage(damage) + { } /** * Return size @@ -121,16 +116,11 @@ class Nitpicker::View_stack void draw_rec(Canvas_base &, Font const &, View const *, Rect) const; /** - * Draw dirty areas + * Draw specified area */ - Dirty_rect draw(Canvas_base &canvas) const + void draw(Canvas_base &canvas, Rect rect) const { - Dirty_rect result = _dirty_rect; - - _dirty_rect.flush([&] (Rect const &rect) { - draw_rec(canvas, _font, _first_view(), rect); }); - - return result; + draw_rec(canvas, _font, _first_view(), rect); } /** @@ -141,19 +131,7 @@ class Nitpicker::View_stack Rect const whole_screen(Point(), _size); _place_labels(whole_screen); - _dirty_rect.mark_as_dirty(whole_screen); - - for (View *view = _first_view(); view; view = view->view_stack_next()) - view->mark_as_dirty(_outline(*view)); - } - - /** - * mark all view-local dirty rectangles a clean - */ - void mark_all_views_as_clean() - { - for (View *view = _first_view(); view; view = view->view_stack_next()) - view->mark_as_clean(); + _damage.mark_as_damaged(whole_screen); } /**