mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 18:56:29 +00:00
nitpicker: Reduce superfluous refresh operations
This commit is contained in:
parent
65e283142a
commit
1ac343fabd
@ -104,6 +104,8 @@ class Chunky_menubar : public Texture<PT>,
|
||||
session_label.string(), WHITE, "", session_color);
|
||||
}
|
||||
|
||||
View &view() override { return *this; }
|
||||
|
||||
using Menubar::state;
|
||||
};
|
||||
|
||||
|
@ -1164,6 +1164,8 @@ void Nitpicker::Main::handle_input(unsigned)
|
||||
framebuffer.refresh(rect.x1(), rect.y1(),
|
||||
rect.w(), rect.h()); });
|
||||
|
||||
user_state.mark_all_views_as_clean();
|
||||
|
||||
/* deliver framebuffer synchronization events */
|
||||
if (!user_state.kill()) {
|
||||
for (::Session *s = session_list.first(); s; s = s->next())
|
||||
|
@ -43,6 +43,8 @@ struct Menubar : Menubar_state
|
||||
virtual void state(Menubar_state) = 0;
|
||||
|
||||
Menubar_state state() const { return *this; }
|
||||
|
||||
virtual View &view() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -41,7 +41,7 @@ User_state::User_state(Global_keys &global_keys, Area view_stack_size, Menubar &
|
||||
{ }
|
||||
|
||||
|
||||
void User_state::_update_all()
|
||||
void User_state::_update_menubar()
|
||||
{
|
||||
Menubar_state state(*this, "", BLACK);
|
||||
|
||||
@ -51,6 +51,14 @@ void User_state::_update_all()
|
||||
_input_receiver->color());
|
||||
|
||||
_menubar.state(state);
|
||||
|
||||
refresh_view(_menubar.view(), _menubar.view().abs_geometry());
|
||||
}
|
||||
|
||||
|
||||
void User_state::_update_all()
|
||||
{
|
||||
_update_menubar();
|
||||
update_all_views();
|
||||
}
|
||||
|
||||
@ -276,5 +284,5 @@ void User_state::focused_session(::Session *session)
|
||||
if (!_global_key_sequence)
|
||||
_input_receiver = session;
|
||||
|
||||
_update_all();
|
||||
_update_menubar();
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ class User_state : public Mode, public View_stack
|
||||
*/
|
||||
bool _global_key_sequence = false;
|
||||
|
||||
void _update_menubar();
|
||||
void _update_all();
|
||||
|
||||
public:
|
||||
|
@ -92,6 +92,7 @@ class View : public Same_buffer_list_elem,
|
||||
Point _buffer_off; /* offset to the visible buffer area */
|
||||
Session &_session; /* session that created the view */
|
||||
char _title[TITLE_LEN];
|
||||
Dirty_rect _dirty_rect;
|
||||
|
||||
Genode::List<View_parent_elem> _children;
|
||||
|
||||
@ -154,7 +155,13 @@ class View : public Same_buffer_list_elem,
|
||||
void remove_child(View const &child) { _children.remove(&child); }
|
||||
|
||||
template <typename FN>
|
||||
void for_each_child(FN const &fn) const {
|
||||
void for_each_child(FN const &fn) {
|
||||
for (View_parent_elem *e = _children.first(); e; e = e->next())
|
||||
fn(*static_cast<View *>(e));
|
||||
}
|
||||
|
||||
template <typename FN>
|
||||
void for_each_const_child(FN const &fn) const {
|
||||
for (View_parent_elem const *e = _children.first(); e; e = e->next())
|
||||
fn(*static_cast<View const *>(e));
|
||||
}
|
||||
@ -242,6 +249,23 @@ class View : public Same_buffer_list_elem,
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_ */
|
||||
|
@ -209,8 +209,9 @@ void View_stack::draw_rec(Canvas_base &canvas, View const *view, Rect rect) cons
|
||||
if (next && left.valid()) draw_rec(canvas, next, left);
|
||||
|
||||
/* draw current view */
|
||||
{
|
||||
Clip_guard clip_guard(canvas, clipped);
|
||||
view->dirty_rect().flush([&] (Rect const &dirty_rect) {
|
||||
|
||||
Clip_guard clip_guard(canvas, Rect::intersect(clipped, dirty_rect));
|
||||
|
||||
/* draw background if view is transparent */
|
||||
if (view->uses_alpha())
|
||||
@ -218,7 +219,7 @@ void View_stack::draw_rec(Canvas_base &canvas, View const *view, Rect rect) cons
|
||||
|
||||
view->frame(canvas, _mode);
|
||||
view->draw(canvas, _mode);
|
||||
}
|
||||
});
|
||||
|
||||
/* draw areas at the bottom/right of the current view */
|
||||
if (next && right.valid()) draw_rec(canvas, next, right);
|
||||
@ -226,14 +227,32 @@ void View_stack::draw_rec(Canvas_base &canvas, View const *view, Rect rect) cons
|
||||
}
|
||||
|
||||
|
||||
void View_stack::refresh_view(View const &view, Rect const rect)
|
||||
void View_stack::refresh_view(View &view, Rect const rect)
|
||||
{
|
||||
/* clip argument agains view outline */
|
||||
Rect const intersection = Rect::intersect(rect, _outline(view));
|
||||
/* rectangle constrained to view geometry */
|
||||
Rect const view_rect = Rect::intersect(rect, _outline(view));
|
||||
|
||||
_dirty_rect.mark_as_dirty(intersection);
|
||||
for (View *v = _first_view(); v; v = v->view_stack_next()) {
|
||||
|
||||
view.for_each_child([&] (View const &child) { refresh_view(child, rect); });
|
||||
Rect const intersection = Rect::intersect(view_rect, _outline(*v));
|
||||
|
||||
if (intersection.valid())
|
||||
_mark_view_as_dirty(*v, intersection);
|
||||
}
|
||||
|
||||
view.for_each_child([&] (View &child) { refresh_view(child, rect); });
|
||||
}
|
||||
|
||||
|
||||
void View_stack::refresh(Rect const rect)
|
||||
{
|
||||
for (View *v = _first_view(); v; v = v->view_stack_next()) {
|
||||
|
||||
Rect const intersection = Rect::intersect(rect, _outline(*v));
|
||||
|
||||
if (intersection.valid())
|
||||
refresh_view(*v, intersection);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -241,10 +260,19 @@ void View_stack::geometry(View &view, Rect const rect)
|
||||
{
|
||||
Rect const old_outline = _outline(view);
|
||||
|
||||
/*
|
||||
* Refresh area covered by the original view geometry.
|
||||
*
|
||||
* We specify the whole geometry to also cover the refresh of child
|
||||
* views. The 'refresh_view' function takes care to constrain the
|
||||
* refresh to the actual view geometry.
|
||||
*/
|
||||
refresh_view(view, Rect(Point(), _size));
|
||||
|
||||
/* change geometry */
|
||||
view.geometry(Rect(rect));
|
||||
|
||||
/* refresh new view geometry */
|
||||
refresh_view(view, Rect(Point(), _size));
|
||||
|
||||
Rect const compound = Rect::compound(old_outline, _outline(view));
|
||||
@ -263,14 +291,14 @@ void View_stack::buffer_offset(View &view, Point const buffer_off)
|
||||
}
|
||||
|
||||
|
||||
void View_stack::stack(View const &view, View const *neighbor, bool behind)
|
||||
void View_stack::stack(View &view, View const *neighbor, bool behind)
|
||||
{
|
||||
_views.remove(&view);
|
||||
_views.insert(&view, _target_stack_position(neighbor, behind));
|
||||
|
||||
_place_labels(view.abs_geometry());
|
||||
|
||||
_dirty_rect.mark_as_dirty(_outline(view));
|
||||
_mark_view_as_dirty(view, _outline(view));
|
||||
}
|
||||
|
||||
|
||||
@ -279,7 +307,7 @@ void View_stack::title(View &view, const char *title)
|
||||
view.title(title);
|
||||
_place_labels(view.abs_geometry());
|
||||
|
||||
_dirty_rect.mark_as_dirty(_outline(view));
|
||||
_mark_view_as_dirty(view, _outline(view));
|
||||
}
|
||||
|
||||
|
||||
@ -298,7 +326,7 @@ View *View_stack::find_view(Point p)
|
||||
|
||||
void View_stack::remove_view(View const &view, bool redraw)
|
||||
{
|
||||
view.for_each_child([&] (View const &child) { remove_view(child); });
|
||||
view.for_each_const_child([&] (View const &child) { remove_view(child); });
|
||||
|
||||
/* remember geometry of view to remove */
|
||||
Rect rect = _outline(view);
|
||||
@ -306,5 +334,5 @@ void View_stack::remove_view(View const &view, bool redraw)
|
||||
/* exclude view from view stack */
|
||||
_views.remove(&view);
|
||||
|
||||
_dirty_rect.mark_as_dirty(rect);
|
||||
refresh(rect);
|
||||
}
|
||||
|
@ -76,6 +76,8 @@ class View_stack
|
||||
void _mark_view_as_dirty(View &view, Rect rect)
|
||||
{
|
||||
_dirty_rect.mark_as_dirty(rect);
|
||||
|
||||
view.mark_as_dirty(rect);
|
||||
}
|
||||
|
||||
public:
|
||||
@ -96,7 +98,8 @@ class View_stack
|
||||
void size(Area size)
|
||||
{
|
||||
_size = size;
|
||||
_dirty_rect.mark_as_dirty(Rect(Point(0, 0), _size));
|
||||
|
||||
update_all_views();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -124,8 +127,23 @@ class View_stack
|
||||
*/
|
||||
void update_all_views()
|
||||
{
|
||||
_place_labels(Rect(Point(), _size));
|
||||
_dirty_rect.mark_as_dirty(Rect(Point(), _size));
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -150,7 +168,7 @@ class View_stack
|
||||
rect.p2() + offset),
|
||||
view->abs_geometry());
|
||||
|
||||
_mark_view_as_dirty(*view, r);
|
||||
refresh_view(*view, r);
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,7 +177,17 @@ class View_stack
|
||||
*
|
||||
* \param view view that should be updated on screen
|
||||
*/
|
||||
void refresh_view(View const &view, Rect);
|
||||
void refresh_view(View &view, Rect);
|
||||
|
||||
/**
|
||||
* Refresh entire view
|
||||
*/
|
||||
void refresh_view(View &view) { refresh_view(view, _outline(view)); }
|
||||
|
||||
/**
|
||||
* Refresh area
|
||||
*/
|
||||
void refresh(Rect);
|
||||
|
||||
/**
|
||||
* Define view geometry
|
||||
@ -186,7 +214,7 @@ class View_stack
|
||||
* bottom of the view stack, specify neighbor = 0 and
|
||||
* behind = false.
|
||||
*/
|
||||
void stack(View const &view, View const *neighbor = 0, bool behind = true);
|
||||
void stack(View &view, View const *neighbor = 0, bool behind = true);
|
||||
|
||||
/**
|
||||
* Set view title
|
||||
|
Loading…
Reference in New Issue
Block a user