151 lines
3.6 KiB
C++
151 lines
3.6 KiB
C++
/*
|
|
* \brief Simplistic redraw manager featuring redraw merging
|
|
* \date 2005-10-24
|
|
* \author Norman Feske <norman.feske@genode-labs.com>
|
|
*/
|
|
|
|
/*
|
|
* 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_ */
|