mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-23 15:32:25 +00:00
parent
fbbd2018bb
commit
cf9eedca47
@ -89,6 +89,7 @@ class Texture_rgb565 : public Canvas::Texture
|
|||||||
int _w, _h; /* size of texture */
|
int _w, _h; /* size of texture */
|
||||||
unsigned char *_alpha; /* alpha channel */
|
unsigned char *_alpha; /* alpha channel */
|
||||||
Pixel_rgb565 *_pixel; /* pixel data */
|
Pixel_rgb565 *_pixel; /* pixel data */
|
||||||
|
bool _preallocated;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -96,23 +97,25 @@ class Texture_rgb565 : public Canvas::Texture
|
|||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
Texture_rgb565(int w, int h)
|
Texture_rgb565(int w, int h)
|
||||||
{
|
:
|
||||||
_w = w;
|
_w(w), _h(h),
|
||||||
_h = h;
|
_alpha((unsigned char *)scout_malloc(w*h)),
|
||||||
_alpha = (unsigned char *)scout_malloc(w*h);
|
_pixel((Pixel_rgb565 *)scout_malloc(w*h*sizeof(Pixel_rgb565))),
|
||||||
_pixel = (Pixel_rgb565 *)scout_malloc(w*h*sizeof(Pixel_rgb565));
|
_preallocated(false)
|
||||||
}
|
{ }
|
||||||
|
|
||||||
Texture_rgb565(Pixel_rgb565 *pixel, unsigned char *alpha, int w, int h):
|
Texture_rgb565(Pixel_rgb565 *pixel, unsigned char *alpha, int w, int h):
|
||||||
_w(w), _h(h), _alpha(alpha), _pixel(pixel) { }
|
_w(w), _h(h), _alpha(alpha), _pixel(pixel), _preallocated(true) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destructor
|
* Destructor
|
||||||
*/
|
*/
|
||||||
~Texture_rgb565()
|
~Texture_rgb565()
|
||||||
{
|
{
|
||||||
|
if (!_preallocated) {
|
||||||
scout_free(_alpha);
|
scout_free(_alpha);
|
||||||
scout_free(_pixel);
|
scout_free(_pixel);
|
||||||
|
}
|
||||||
_w = _h = 0;
|
_w = _h = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,6 +164,11 @@ class Element
|
|||||||
*/
|
*/
|
||||||
virtual void format_fixed_width(int w) { }
|
virtual void format_fixed_width(int w) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format element and all child elements to specified width and height
|
||||||
|
*/
|
||||||
|
virtual void format_fixed_size(int w, int h) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw function
|
* Draw function
|
||||||
*
|
*
|
||||||
|
@ -17,10 +17,13 @@
|
|||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "titlebar.h"
|
#include "titlebar.h"
|
||||||
#include "sky_texture.h"
|
#include "sky_texture.h"
|
||||||
|
#include "fade_icon.h"
|
||||||
|
|
||||||
#define TITLEBAR_RGBA _binary_titlebar_rgba_start
|
#define TITLEBAR_RGBA _binary_titlebar_rgba_start
|
||||||
|
#define SIZER_RGBA _binary_sizer_rgba_start
|
||||||
|
|
||||||
extern unsigned char TITLEBAR_RGBA[];
|
extern unsigned char TITLEBAR_RGBA[];
|
||||||
|
extern unsigned char SIZER_RGBA[];
|
||||||
|
|
||||||
|
|
||||||
template <typename PT>
|
template <typename PT>
|
||||||
@ -39,7 +42,9 @@ class Framebuffer_window : public Window
|
|||||||
Titlebar<PT> _titlebar;
|
Titlebar<PT> _titlebar;
|
||||||
Sky_texture<PT, 512, 512> _bg_texture;
|
Sky_texture<PT, 512, 512> _bg_texture;
|
||||||
int _bg_offset;
|
int _bg_offset;
|
||||||
|
Fade_icon<PT, 32, 32> _sizer;
|
||||||
Element *_content;
|
Element *_content;
|
||||||
|
bool _config_alpha;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -49,7 +54,8 @@ class Framebuffer_window : public Window
|
|||||||
Framebuffer_window(Platform *pf,
|
Framebuffer_window(Platform *pf,
|
||||||
Redraw_manager *redraw,
|
Redraw_manager *redraw,
|
||||||
Element *content,
|
Element *content,
|
||||||
const char *name)
|
const char *name,
|
||||||
|
bool config_alpha)
|
||||||
:
|
:
|
||||||
Window(pf, redraw, content->min_w() + 2, content->min_h() + 1 + _TH),
|
Window(pf, redraw, content->min_w() + 2, content->min_h() + 1 + _TH),
|
||||||
_bg_offset(0), _content(content)
|
_bg_offset(0), _content(content)
|
||||||
@ -59,8 +65,14 @@ class Framebuffer_window : public Window
|
|||||||
_titlebar.text(name);
|
_titlebar.text(name);
|
||||||
_titlebar.event_handler(new Mover_event_handler(this));
|
_titlebar.event_handler(new Mover_event_handler(this));
|
||||||
|
|
||||||
|
/* resize handle */
|
||||||
|
_sizer.rgba(SIZER_RGBA);
|
||||||
|
_sizer.event_handler(new Sizer_event_handler(this));
|
||||||
|
_sizer.alpha(100);
|
||||||
|
|
||||||
append(&_titlebar);
|
append(&_titlebar);
|
||||||
append(_content);
|
append(_content);
|
||||||
|
append(&_sizer);
|
||||||
|
|
||||||
_min_w = max_w();
|
_min_w = max_w();
|
||||||
_min_h = max_h();
|
_min_h = max_h();
|
||||||
@ -71,10 +83,23 @@ class Framebuffer_window : public Window
|
|||||||
*/
|
*/
|
||||||
void format(int w, int h)
|
void format(int w, int h)
|
||||||
{
|
{
|
||||||
|
w = (w > max_w()) ? max_w() : w;
|
||||||
|
h = (h > max_h()) ? max_h() : h;
|
||||||
_w = w;
|
_w = w;
|
||||||
_h = h;
|
_h = h;
|
||||||
|
|
||||||
Parent_element::_format_children(1, w);
|
int y = 0;
|
||||||
|
|
||||||
|
_titlebar.format_fixed_width(w);
|
||||||
|
_titlebar.geometry(1, y, _titlebar.min_w(), _titlebar.min_h());
|
||||||
|
y += _titlebar.min_h();
|
||||||
|
|
||||||
|
int const content_h = (h > y + 1) ? (h - y - 1) : 0;
|
||||||
|
int const content_w = w - 2;
|
||||||
|
_content->format_fixed_size(content_w, content_h);
|
||||||
|
_content->geometry(1, y, content_w, content_h);
|
||||||
|
|
||||||
|
_sizer.geometry(_w - 32, _h - 32, 32, 32);
|
||||||
|
|
||||||
pf()->view_geometry(pf()->vx(), pf()->vy(), _w, _h);
|
pf()->view_geometry(pf()->vx(), pf()->vy(), _w, _h);
|
||||||
redraw()->size(_w, _h);
|
redraw()->size(_w, _h);
|
||||||
@ -91,6 +116,7 @@ class Framebuffer_window : public Window
|
|||||||
*/
|
*/
|
||||||
void draw(Canvas *c, int x, int y)
|
void draw(Canvas *c, int x, int y)
|
||||||
{
|
{
|
||||||
|
if (_config_alpha)
|
||||||
_bg_texture.draw(c, 0, - _bg_offset);
|
_bg_texture.draw(c, 0, - _bg_offset);
|
||||||
|
|
||||||
::Parent_element::draw(c, x, y);
|
::Parent_element::draw(c, x, y);
|
||||||
|
@ -162,7 +162,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
/* create instance of browser window */
|
/* create instance of browser window */
|
||||||
static Framebuffer_window<Pixel_rgb565>
|
static Framebuffer_window<Pixel_rgb565>
|
||||||
fb_win(&pf, &redraw, window_content(), config_title);
|
fb_win(&pf, &redraw, window_content(), config_title, config_alpha);
|
||||||
|
|
||||||
if (config_animate) {
|
if (config_animate) {
|
||||||
static Background_animator fb_win_bg_anim(&fb_win);
|
static Background_animator fb_win_bg_anim(&fb_win);
|
||||||
@ -181,8 +181,11 @@ int main(int argc, char **argv)
|
|||||||
Event ev;
|
Event ev;
|
||||||
unsigned long curr_time, old_time;
|
unsigned long curr_time, old_time;
|
||||||
curr_time = old_time = pf.timer_ticks();
|
curr_time = old_time = pf.timer_ticks();
|
||||||
|
lock_window_content();
|
||||||
do {
|
do {
|
||||||
|
unlock_window_content();
|
||||||
pf.get_event(&ev);
|
pf.get_event(&ev);
|
||||||
|
lock_window_content();
|
||||||
|
|
||||||
if (ev.type != Event::WHEEL) {
|
if (ev.type != Event::WHEEL) {
|
||||||
ev.mx -= user_state.vx();
|
ev.mx -= user_state.vx();
|
||||||
|
@ -90,15 +90,21 @@ class Window_content : public Element
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
Genode::Lock &_lock;
|
||||||
Event_queue *_ev_queue;
|
Event_queue *_ev_queue;
|
||||||
int _omx, _omy;
|
int _omx, _omy;
|
||||||
Element *_element;
|
Element *_element;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Content_event_handler(Event_queue *ev_queue, Element *element):
|
Content_event_handler(Event_queue *ev_queue, Element *element,
|
||||||
_ev_queue(ev_queue), _element(element) { }
|
Genode::Lock &lock)
|
||||||
|
:
|
||||||
|
_lock(lock), _ev_queue(ev_queue), _element(element) { }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called from main program with taken lock for window content
|
||||||
|
*/
|
||||||
void handle(Event &ev)
|
void handle(Event &ev)
|
||||||
{
|
{
|
||||||
int mx = ev.mx - _element->abs_x();
|
int mx = ev.mx - _element->abs_x();
|
||||||
@ -124,35 +130,29 @@ class Window_content : public Element
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned _fb_w, _fb_h;
|
struct Fb_texture
|
||||||
Genode::Attached_ram_dataspace _fb_ds;
|
|
||||||
Pixel_rgb565 *_pixel;
|
|
||||||
unsigned char *_alpha;
|
|
||||||
Texture_rgb565 _fb_texture;
|
|
||||||
Content_event_handler _ev_handler;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Window_content(unsigned fb_w, unsigned fb_h, Event_queue *ev_queue,
|
|
||||||
bool config_alpha)
|
|
||||||
:
|
|
||||||
_fb_w(fb_w), _fb_h(fb_h),
|
|
||||||
_fb_ds(Genode::env()->ram_session(), _fb_w*_fb_h*sizeof(Pixel_rgb565)),
|
|
||||||
_pixel(_fb_ds.local_addr<Pixel_rgb565>()),
|
|
||||||
_alpha((unsigned char *)Genode::env()->heap()->alloc(_fb_w*_fb_h)),
|
|
||||||
_fb_texture(_pixel, _alpha, _fb_w, _fb_h),
|
|
||||||
_ev_handler(ev_queue, this)
|
|
||||||
{
|
{
|
||||||
_min_w = _fb_w;
|
unsigned w, h;
|
||||||
_min_h = _fb_h;
|
Genode::Attached_ram_dataspace ds;
|
||||||
|
Pixel_rgb565 *pixel;
|
||||||
|
unsigned char *alpha;
|
||||||
|
Texture_rgb565 texture;
|
||||||
|
|
||||||
|
Fb_texture(unsigned w, unsigned h, bool config_alpha)
|
||||||
|
:
|
||||||
|
w(w), h(h),
|
||||||
|
ds(Genode::env()->ram_session(), w*h*sizeof(Pixel_rgb565)),
|
||||||
|
pixel(ds.local_addr<Pixel_rgb565>()),
|
||||||
|
alpha((unsigned char *)Genode::env()->heap()->alloc(w*h)),
|
||||||
|
texture(pixel, alpha, w, h)
|
||||||
|
{
|
||||||
int alpha_min = config_alpha ? 0 : 255;
|
int alpha_min = config_alpha ? 0 : 255;
|
||||||
|
|
||||||
/* init alpha channel */
|
/* init alpha channel */
|
||||||
for (unsigned y = 0; y < _fb_h; y++)
|
for (unsigned y = 0; y < h; y++)
|
||||||
for (unsigned x = 0; x < _fb_w; x++) {
|
for (unsigned x = 0; x < w; x++) {
|
||||||
|
|
||||||
int v = (x * y + (_fb_w*_fb_h)/4) / _fb_w;
|
int v = (x * y + (w*h)/4) / w;
|
||||||
v = v + (x + y)/2;
|
v = v + (x + y)/2;
|
||||||
int a = v & 0xff;
|
int a = v & 0xff;
|
||||||
if (v & 0x100)
|
if (v & 0x100)
|
||||||
@ -160,24 +160,113 @@ class Window_content : public Element
|
|||||||
|
|
||||||
a += (dither_matrix[y % dither_size][x % dither_size] - 127) >> 4;
|
a += (dither_matrix[y % dither_size][x % dither_size] - 127) >> 4;
|
||||||
|
|
||||||
_alpha[y*_fb_w + x] = Genode::max(alpha_min, Genode::min(a, 255));
|
alpha[y*w + x] = Genode::max(alpha_min, Genode::min(a, 255));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~Fb_texture()
|
||||||
|
{
|
||||||
|
Genode::env()->heap()->free(alpha, w*h);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Genode::Lock _lock;
|
||||||
|
bool _config_alpha;
|
||||||
|
Content_event_handler _ev_handler;
|
||||||
|
Fb_texture *_fb;
|
||||||
|
unsigned _new_w, _new_h;
|
||||||
|
Genode::Signal_context_capability _mode_sigh;
|
||||||
|
bool _wait_for_refresh;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Window_content(unsigned fb_w, unsigned fb_h, Event_queue *ev_queue,
|
||||||
|
bool config_alpha)
|
||||||
|
:
|
||||||
|
_config_alpha(config_alpha),
|
||||||
|
_ev_handler(ev_queue, this, _lock),
|
||||||
|
_fb(new (Genode::env()->heap()) Fb_texture(fb_w, fb_h, _config_alpha)),
|
||||||
|
_new_w(fb_w), _new_h(fb_h),
|
||||||
|
_wait_for_refresh(false)
|
||||||
|
{
|
||||||
|
_min_w = _fb->w;
|
||||||
|
_min_h = _fb->h;
|
||||||
|
|
||||||
event_handler(&_ev_handler);
|
event_handler(&_ev_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Accessors
|
* Accessors, called by the RPC entrypoint. Hence, the need for
|
||||||
|
* locking.
|
||||||
*/
|
*/
|
||||||
Genode::Dataspace_capability fb_ds_cap() { return _fb_ds.cap(); }
|
|
||||||
unsigned fb_w() { return _fb_w; }
|
Genode::Dataspace_capability fb_ds_cap() {
|
||||||
unsigned fb_h() { return _fb_h; }
|
Genode::Lock::Guard guard(_lock);
|
||||||
|
return _fb->ds.cap();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned fb_w() {
|
||||||
|
Genode::Lock::Guard guard(_lock);
|
||||||
|
return _fb->w;
|
||||||
|
}
|
||||||
|
unsigned fb_h() {
|
||||||
|
Genode::Lock::Guard guard(_lock);
|
||||||
|
return _fb->h;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mode_sigh(Genode::Signal_context_capability sigh)
|
||||||
|
{
|
||||||
|
Genode::Lock::Guard guard(_lock);
|
||||||
|
_mode_sigh = sigh;
|
||||||
|
}
|
||||||
|
|
||||||
|
void realloc_framebuffer()
|
||||||
|
{
|
||||||
|
Genode::Lock::Guard guard(_lock);
|
||||||
|
|
||||||
|
/* skip reallocation if size has not changed */
|
||||||
|
if (_new_w == _fb->w && _new_h == _fb->h)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Genode::destroy(Genode::env()->heap(), _fb);
|
||||||
|
|
||||||
|
_fb = new (Genode::env()->heap())
|
||||||
|
Fb_texture(_new_w, _new_h, _config_alpha);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Suppress drawing of the texture until we received the next
|
||||||
|
* refresh call from the client. This way, we avoid flickering
|
||||||
|
* artifacts while continuously resizing the window.
|
||||||
|
*/
|
||||||
|
_wait_for_refresh = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_called_refresh() { _wait_for_refresh = false; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Element interface
|
* Element interface
|
||||||
|
*
|
||||||
|
* Called indirectly by the Content_event_handler thread, which has
|
||||||
|
* already taken the lock.
|
||||||
*/
|
*/
|
||||||
void draw(Canvas *c, int x, int y) {
|
void draw(Canvas *c, int x, int y)
|
||||||
c->draw_texture(&_fb_texture, _x + x, _y + y); }
|
{
|
||||||
|
if (!_wait_for_refresh)
|
||||||
|
c->draw_texture(&_fb->texture, _x + x, _y + y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void format_fixed_size(int w, int h)
|
||||||
|
{
|
||||||
|
_new_w = w, _new_h = h;
|
||||||
|
|
||||||
|
/* notify framebuffer client about mode change */
|
||||||
|
if (_mode_sigh.valid())
|
||||||
|
Genode::Signal_transmitter(_mode_sigh).submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void lock() { _lock.lock(); }
|
||||||
|
void unlock() { _lock.unlock(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -185,6 +274,9 @@ static Window_content *_window_content;
|
|||||||
|
|
||||||
Element *window_content() { return _window_content; }
|
Element *window_content() { return _window_content; }
|
||||||
|
|
||||||
|
void lock_window_content() { _window_content->lock(); }
|
||||||
|
void unlock_window_content() { _window_content->unlock(); }
|
||||||
|
|
||||||
|
|
||||||
/***********************************************
|
/***********************************************
|
||||||
** Implementation of the framebuffer service **
|
** Implementation of the framebuffer service **
|
||||||
@ -194,39 +286,58 @@ namespace Framebuffer
|
|||||||
{
|
{
|
||||||
class Session_component : public Genode::Rpc_object<Session>
|
class Session_component : public Genode::Rpc_object<Session>
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
Window_content &_window_content;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Genode::Dataspace_capability dataspace() {
|
Session_component(Window_content &window_content)
|
||||||
return _window_content->fb_ds_cap(); }
|
: _window_content(window_content) { }
|
||||||
|
|
||||||
void release() { }
|
Genode::Dataspace_capability dataspace() {
|
||||||
|
return _window_content.fb_ds_cap(); }
|
||||||
|
|
||||||
|
void release() {
|
||||||
|
_window_content.realloc_framebuffer(); }
|
||||||
|
|
||||||
Mode mode() const
|
Mode mode() const
|
||||||
{
|
{
|
||||||
return Mode(_window_content->fb_w(), _window_content->fb_h(),
|
return Mode(_window_content.fb_w(), _window_content.fb_h(),
|
||||||
Mode::RGB565);
|
Mode::RGB565);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mode_sigh(Genode::Signal_context_capability) { }
|
void mode_sigh(Genode::Signal_context_capability sigh) {
|
||||||
|
_window_content.mode_sigh(sigh); }
|
||||||
|
|
||||||
void refresh(int x, int y, int w, int h) {
|
void refresh(int x, int y, int w, int h)
|
||||||
window_content()->redraw_area(x, y, w, h); }
|
{
|
||||||
|
_window_content.client_called_refresh();
|
||||||
|
_window_content.redraw_area(x, y, w, h);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Root : public Genode::Root_component<Session_component>
|
class Root : public Genode::Root_component<Session_component>
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
Window_content &_window_content;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
Session_component *_create_session(const char *args) {
|
Session_component *_create_session(const char *args) {
|
||||||
PDBG("creating framebuffer session");
|
return new (md_alloc()) Session_component(_window_content); }
|
||||||
return new (md_alloc()) Session_component(); }
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Root(Genode::Rpc_entrypoint *session_ep,
|
Root(Genode::Rpc_entrypoint *session_ep,
|
||||||
Genode::Allocator *md_alloc)
|
Genode::Allocator *md_alloc,
|
||||||
: Genode::Root_component<Session_component>(session_ep, md_alloc) { }
|
Window_content &window_content)
|
||||||
|
:
|
||||||
|
Genode::Root_component<Session_component>(session_ep, md_alloc),
|
||||||
|
_window_content(window_content)
|
||||||
|
{ }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,7 +359,7 @@ void init_services(unsigned fb_w, unsigned fb_h, bool config_alpha)
|
|||||||
/*
|
/*
|
||||||
* Let the entry point serve the framebuffer and input root interfaces
|
* Let the entry point serve the framebuffer and input root interfaces
|
||||||
*/
|
*/
|
||||||
static Framebuffer::Root fb_root(&ep, env()->heap());
|
static Framebuffer::Root fb_root(&ep, env()->heap(), content);
|
||||||
static Input::Root input_root(&ep, env()->heap());
|
static Input::Root input_root(&ep, env()->heap());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -19,5 +19,7 @@
|
|||||||
|
|
||||||
extern Element *window_content();
|
extern Element *window_content();
|
||||||
extern void init_services(unsigned fb_w, unsigned fb_h, bool config_alpha);
|
extern void init_services(unsigned fb_w, unsigned fb_h, bool config_alpha);
|
||||||
|
extern void lock_window_content();
|
||||||
|
extern void unlock_window_content();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user