/* * \brief Simplistic redraw manager featuring redraw merging * \date 2005-10-24 * \author Norman Feske */ /* * Copyright (C) 2005-2013 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ #ifndef _REDRAW_MANAGER_H_ #define _REDRAW_MANAGER_H_ #include "elements.h" class Redraw_manager { private: int _x1, _y1; /* upper left pixel of dirty area */ int _x2, _y2; /* lower right pixel of dirty area */ int _cnt; /* nb of requests since last process */ Element *_root; /* root element for drawing */ Canvas *_canvas; /* graphics backend */ Screen_update *_scr_update; /* flushing pixels in backend */ int _w, _h; /* current size of output window */ bool _scout_quirk; /* enable redraw quirk for scout */ public: /** * Constructor */ Redraw_manager(Canvas *canvas, Screen_update *scr_update, int w, int h, bool scout_quirk = false) : _cnt(0), _root(0), _canvas(canvas), _scr_update(scr_update), _w(w), _h(h), _scout_quirk(scout_quirk) { } /** * Accessor functions */ inline Canvas *canvas() { return _canvas; } /** * Define root element for issueing drawing operations */ inline void root(Element *root) { _root = root; } /** * Collect redraw requests */ void request(int x, int y, int w, int h) { /* * Scout redraw quirk * * Quick fix to avoid artifacts at the icon bar. * The icon bar must always be drawn completely * because of the interaction of the different * layers. */ if (_scout_quirk && y < 64 + 32) { h = max(h + y, 64 + 32); w = _w; x = 0; y = 0; } /* first request since last process operation */ if (_cnt == 0) { _x1 = x; _x2 = x + w - 1; _y1 = y; _y2 = y + h - 1; /* merge subsequencing requests */ } else { _x1 = min(_x1, x); _x2 = max(_x2, x + w - 1); _y1 = min(_y1, y); _y2 = max(_y2, y + h - 1); } _cnt++; } /** * Define size of visible redraw window */ void size(int w, int h) { if (w > _canvas->w()) w = _canvas->w(); if (h > _canvas->h()) h = _canvas->h(); _w = w; _h = h; } /** * Process redrawing operations */ void process() { if (_cnt == 0 || !_canvas || !_root) return; /* get actual drawing area (clipped against canvas dimensions) */ int x1 = max(0, _x1); int y1 = max(0, _y1); int x2 = min(_w - 1, _x2); int y2 = min(_h - 1, _y2); if (x1 > x2 || y1 > y2) return; _canvas->clip(x1, y1, x2 - x1 + 1, y2 - y1 + 1); /* draw browser window into back buffer */ _root->try_draw(_canvas, 0, 0); /* * If we draw the whole area, we can flip the front * and back buffers instead of copying pixels from the * back to the front buffer. */ /* detemine if the whole area must be drawn */ if (x1 == 0 && x2 == _root->w() - 1 && y1 == 0 && y2 == _root->h() - 1) { /* flip back end front buffers */ _scr_update->flip_buf_scr(); /* apply future drawing operations on new back buffer */ _canvas->addr(_scr_update->buf_adr()); } else _scr_update->copy_buf_to_scr(x1, y1, x2 - x1 + 1, y2 - y1 + 1); /* give notification about changed canvas area */ if (_scr_update) _scr_update->scr_update(x1, y1, x2 - x1 + 1, y2 - y1 + 1); /* reset request state */ _cnt = 0; } }; #endif /* _REDRAW_MANAGER_H_ */