os: Add 'Framebuffer::Session::sync_sigh'

The new framebuffer-session function allows a client to register a
handler for receiving display-synchronization events.
This commit is contained in:
Norman Feske 2014-04-29 15:32:09 +02:00
parent 0b04f9de25
commit 5de17d4223
16 changed files with 237 additions and 124 deletions

View File

@ -276,29 +276,37 @@ namespace Framebuffer
Window_content &_window_content; Window_content &_window_content;
Genode::Signal_context_capability _sync_sigh;
public: public:
Session_component(Window_content &window_content) Session_component(Window_content &window_content)
: _window_content(window_content) { } : _window_content(window_content) { }
Genode::Dataspace_capability dataspace() Genode::Dataspace_capability dataspace() override
{ {
_window_content.realloc_framebuffer(); _window_content.realloc_framebuffer();
return _window_content.fb_ds_cap(); return _window_content.fb_ds_cap();
} }
Mode mode() const Mode mode() const override
{ {
return Mode(_window_content.mode_size().w(), return Mode(_window_content.mode_size().w(),
_window_content.mode_size().h(), Mode::RGB565); _window_content.mode_size().h(), Mode::RGB565);
} }
void mode_sigh(Genode::Signal_context_capability sigh) { void mode_sigh(Genode::Signal_context_capability sigh) override {
_window_content.mode_sigh(sigh); } _window_content.mode_sigh(sigh); }
void refresh(int x, int y, int w, int h) void sync_sigh(Genode::Signal_context_capability sigh) override {
_sync_sigh = sigh; }
void refresh(int x, int y, int w, int h) override
{ {
_window_content.redraw_area(x, y, w, h); _window_content.redraw_area(x, y, w, h);
if (_sync_sigh.valid())
Genode::Signal_transmitter(_sync_sigh).submit();
} }
}; };
@ -311,7 +319,7 @@ namespace Framebuffer
protected: protected:
Session_component *_create_session(const char *args) { Session_component *_create_session(const char *args) override {
return new (md_alloc()) Session_component(_window_content); } return new (md_alloc()) Session_component(_window_content); }
public: public:

View File

@ -76,6 +76,11 @@ namespace Framebuffer {
} }
void Session_component::sync_sigh(Genode::Signal_context_capability sigh_cap)
{
_framebuffer.sync_sigh(sigh_cap);
}
void Session_component::refresh(int x, int y, int w, int h) void Session_component::refresh(int x, int y, int w, int h)
{ {
_framebuffer.refresh(x, y, w, h); _framebuffer.refresh(x, y, w, h);

View File

@ -45,10 +45,11 @@ namespace Framebuffer {
int max_width = 0, int max_width = 0,
int max_height = 0); int max_height = 0);
Genode::Dataspace_capability dataspace(); Genode::Dataspace_capability dataspace() override;
Mode mode() const; Mode mode() const override;
void mode_sigh(Genode::Signal_context_capability sigh_cap); void mode_sigh(Genode::Signal_context_capability) override;
void refresh(int x, int y, int w, int h); void sync_sigh(Genode::Signal_context_capability) override;
void refresh(int, int, int, int) override;
}; };
} }

View File

@ -94,6 +94,30 @@ namespace Framebuffer {
Genode::Dataspace_capability _fb_ds; Genode::Dataspace_capability _fb_ds;
void *_fb_addr; void *_fb_addr;
Genode::Signal_context_capability _sync_sigh;
void _refresh_buffered(int x, int y, int w, int h)
{
/* clip specified coordinates against screen boundaries */
int x2 = min(x + w - 1, (int)_scr_width - 1),
y2 = min(y + h - 1, (int)_scr_height - 1);
int x1 = max(x, 0),
y1 = max(y, 0);
if (x1 > x2 || y1 > y2) return;
/* determine bytes per pixel */
int bypp = 0;
if (_scr_mode == 16) bypp = 2;
if (!bypp) return;
/* copy pixels from back buffer to physical frame buffer */
char *src = (char *)_bb_addr + bypp*(_scr_width*y + x),
*dst = (char *)_fb_addr + bypp*(_scr_width*y + x);
blit(src, bypp*_scr_width, dst, bypp*_scr_width,
bypp*(x2 - x1 + 1), y2 - y1 + 1);
}
public: public:
/** /**
@ -146,43 +170,30 @@ namespace Framebuffer {
** Framebuffer session interface ** ** Framebuffer session interface **
***********************************/ ***********************************/
Dataspace_capability dataspace() { Dataspace_capability dataspace() override {
return _buffered ? Dataspace_capability(_bb_ds) return _buffered ? Dataspace_capability(_bb_ds)
: Dataspace_capability(_fb_ds); } : Dataspace_capability(_fb_ds); }
void release() { } Mode mode() const override
Mode mode() const
{ {
return Mode(_scr_width, _scr_height, return Mode(_scr_width, _scr_height,
_scr_mode == 16 ? Mode::RGB565 : Mode::INVALID); _scr_mode == 16 ? Mode::RGB565 : Mode::INVALID);
} }
void mode_sigh(Genode::Signal_context_capability) { } void mode_sigh(Genode::Signal_context_capability) override { }
/* not implemented */ void sync_sigh(Genode::Signal_context_capability sigh) override
void refresh(int x, int y, int w, int h)
{ {
if (!_buffered) return; _sync_sigh = sigh;
}
/* clip specified coordinates against screen boundaries */ void refresh(int x, int y, int w, int h) override
int x2 = min(x + w - 1, (int)_scr_width - 1), {
y2 = min(y + h - 1, (int)_scr_height - 1); if (_buffered)
int x1 = max(x, 0), _refresh_buffered(x, y, w, h);
y1 = max(y, 0);
if (x1 > x2 || y1 > y2) return;
/* determine bytes per pixel */ if (_sync_sigh.valid())
int bypp = 0; Signal_transmitter(_sync_sigh).submit();
if (_scr_mode == 16) bypp = 2;
if (!bypp) return;
/* copy pixels from back buffer to physical frame buffer */
char *src = (char *)_bb_addr + bypp*(_scr_width*y + x),
*dst = (char *)_fb_addr + bypp*(_scr_width*y + x);
blit(src, bypp*_scr_width, dst, bypp*_scr_width,
bypp*(x2 - x1 + 1), y2 - y1 + 1);
} }
}; };
@ -196,7 +207,7 @@ namespace Framebuffer {
{ {
protected: protected:
Session_component *_create_session(const char *args) Session_component *_create_session(const char *args) override
{ {
unsigned long scr_width = session_arg("width", args, "fb_width", 1024), unsigned long scr_width = session_arg("width", args, "fb_width", 1024),
scr_height = session_arg("height", args, "fb_height", 768), scr_height = session_arg("height", args, "fb_height", 768),

View File

@ -24,15 +24,18 @@ namespace Framebuffer {
explicit Session_client(Session_capability session) explicit Session_client(Session_capability session)
: Genode::Rpc_client<Session>(session) { } : Genode::Rpc_client<Session>(session) { }
Genode::Dataspace_capability dataspace() { Genode::Dataspace_capability dataspace() override {
return call<Rpc_dataspace>(); } return call<Rpc_dataspace>(); }
Mode mode() const { return call<Rpc_mode>(); } Mode mode() const override { return call<Rpc_mode>(); }
void mode_sigh(Genode::Signal_context_capability sigh) { void mode_sigh(Genode::Signal_context_capability sigh) override {
call<Rpc_mode_sigh>(sigh); } call<Rpc_mode_sigh>(sigh); }
void refresh(int x, int y, int w, int h) { void sync_sigh(Genode::Signal_context_capability sigh) override {
call<Rpc_sync_sigh>(sigh); }
void refresh(int x, int y, int w, int h) override {
call<Rpc_refresh>(x, y, w, h); } call<Rpc_refresh>(x, y, w, h); }
}; };
} }

View File

@ -105,6 +105,11 @@ namespace Framebuffer {
*/ */
virtual void refresh(int x, int y, int w, int h) = 0; virtual void refresh(int x, int y, int w, int h) = 0;
/**
* Register signal handler for refresh synchronization
*/
virtual void sync_sigh(Genode::Signal_context_capability) = 0;
/********************* /*********************
** RPC declaration ** ** RPC declaration **
@ -114,8 +119,10 @@ namespace Framebuffer {
GENODE_RPC(Rpc_mode, Mode, mode); GENODE_RPC(Rpc_mode, Mode, mode);
GENODE_RPC(Rpc_refresh, void, refresh, int, int, int, int); GENODE_RPC(Rpc_refresh, void, refresh, int, int, int, int);
GENODE_RPC(Rpc_mode_sigh, void, mode_sigh, Genode::Signal_context_capability); GENODE_RPC(Rpc_mode_sigh, void, mode_sigh, Genode::Signal_context_capability);
GENODE_RPC(Rpc_sync_sigh, void, sync_sigh, Genode::Signal_context_capability);
GENODE_RPC_INTERFACE(Rpc_dataspace, Rpc_mode, Rpc_mode_sigh, Rpc_refresh); GENODE_RPC_INTERFACE(Rpc_dataspace, Rpc_mode, Rpc_mode_sigh, Rpc_refresh,
Rpc_sync_sigh);
}; };
} }

View File

@ -25,18 +25,21 @@ namespace Framebuffer {
explicit Imx_client(Capability<Imx_session> session) explicit Imx_client(Capability<Imx_session> session)
: Genode::Rpc_client<Imx_session>(session) { } : Genode::Rpc_client<Imx_session>(session) { }
Genode::Dataspace_capability dataspace() { Genode::Dataspace_capability dataspace() override {
return call<Rpc_dataspace>(); } return call<Rpc_dataspace>(); }
Mode mode() const { return call<Rpc_mode>(); } Mode mode() const override { return call<Rpc_mode>(); }
void mode_sigh(Genode::Signal_context_capability sigh) { void mode_sigh(Genode::Signal_context_capability sigh) override {
call<Rpc_mode_sigh>(sigh); } call<Rpc_mode_sigh>(sigh); }
void refresh(int x, int y, int w, int h) { void sync_sigh(Genode::Signal_context_capability sigh) override {
call<Rpc_sync_sigh>(sigh); }
void refresh(int x, int y, int w, int h) override {
call<Rpc_refresh>(x, y, w, h); } call<Rpc_refresh>(x, y, w, h); }
void overlay(Genode::addr_t phys_addr, int x, int y, int alpha) { void overlay(Genode::addr_t phys_addr, int x, int y, int alpha) override {
call<Rpc_overlay>(phys_addr, x, y, alpha); } call<Rpc_overlay>(phys_addr, x, y, alpha); }
}; };
} }

View File

@ -45,6 +45,7 @@ class Framebuffer::Session_component
size_t _size; size_t _size;
Dataspace_capability _ds; Dataspace_capability _ds;
addr_t _phys_base; addr_t _phys_base;
Signal_context_capability _sync_sigh;
/** /**
* Convert Driver::Format to Framebuffer::Mode::Format * Convert Driver::Format to Framebuffer::Mode::Format
@ -88,16 +89,25 @@ class Framebuffer::Session_component
** Framebuffer::Session interface ** ** Framebuffer::Session interface **
************************************/ ************************************/
Dataspace_capability dataspace() { return _ds; } Dataspace_capability dataspace() override { return _ds; }
Mode mode() const Mode mode() const override
{ {
return Mode(_width, _height, _convert_format(_format)); return Mode(_width, _height, _convert_format(_format));
} }
void mode_sigh(Genode::Signal_context_capability) { } void mode_sigh(Genode::Signal_context_capability) override { }
void refresh(int, int, int, int) { } void sync_sigh(Genode::Signal_context_capability sigh) override
{
_sync_sigh = sigh;
}
void refresh(int, int, int, int) override
{
if (_sync_sigh.valid())
Signal_transmitter(_sync_sigh).submit();
}
}; };

View File

@ -41,8 +41,29 @@ class Framebuffer::Session_component :
Genode::Dataspace_capability _fb_ds; Genode::Dataspace_capability _fb_ds;
void *_fb_addr; void *_fb_addr;
Signal_context_capability _sync_sigh;
Ipu &_ipu; Ipu &_ipu;
void _refresh_buffered(int x, int y, int w, int h)
{
/* clip specified coordinates against screen boundaries */
int x2 = min(x + w - 1, (int)_mode.width() - 1),
y2 = min(y + h - 1, (int)_mode.height() - 1);
int x1 = max(x, 0),
y1 = max(y, 0);
if (x1 > x2 || y1 > y2) return;
int bypp = _mode.bytes_per_pixel();
/* copy pixels from back buffer to physical frame buffer */
char *src = (char *)_bb_addr + bypp*(_mode.width()*y + x),
*dst = (char *)_fb_addr + bypp*(_mode.width()*y + x);
blit(src, bypp*_mode.width(), dst, bypp*_mode.width(),
bypp*(x2 - x1 + 1), y2 - y1 + 1);
}
public: public:
Session_component(Driver &driver, bool buffered) Session_component(Driver &driver, bool buffered)
@ -68,29 +89,22 @@ class Framebuffer::Session_component :
** Framebuffer::session interface ** ** Framebuffer::session interface **
**************************************/ **************************************/
Dataspace_capability dataspace() { return _buffered ? _bb_ds : _fb_ds; } Dataspace_capability dataspace() override { return _buffered ? _bb_ds : _fb_ds; }
Mode mode() const { return _mode; } Mode mode() const override { return _mode; }
void mode_sigh(Genode::Signal_context_capability) { } void mode_sigh(Genode::Signal_context_capability) override { }
void refresh(int x, int y, int w, int h) void sync_sigh(Genode::Signal_context_capability sigh) override
{ {
if (!_buffered) return; _sync_sigh = sigh;
}
/* clip specified coordinates against screen boundaries */ void refresh(int x, int y, int w, int h) override
int x2 = min(x + w - 1, (int)_mode.width() - 1), {
y2 = min(y + h - 1, (int)_mode.height() - 1); if (_buffered)
int x1 = max(x, 0), _refresh_buffered(x, y, w, h);
y1 = max(y, 0);
if (x1 > x2 || y1 > y2) return;
int bypp = _mode.bytes_per_pixel(); if (_sync_sigh.valid())
Signal_transmitter(_sync_sigh).submit();
/* copy pixels from back buffer to physical frame buffer */
char *src = (char *)_bb_addr + bypp*(_mode.width()*y + x),
*dst = (char *)_fb_addr + bypp*(_mode.width()*y + x);
blit(src, bypp*_mode.width(), dst, bypp*_mode.width(),
bypp*(x2 - x1 + 1), y2 - y1 + 1);
} }
void overlay(Genode::addr_t phys_base, int x, int y, int alpha) { void overlay(Genode::addr_t phys_base, int x, int y, int alpha) {

View File

@ -40,6 +40,7 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Framebuffer::Se
size_t _size; size_t _size;
Dataspace_capability _ds; Dataspace_capability _ds;
addr_t _phys_base; addr_t _phys_base;
Signal_context_capability _sync_sigh;
/** /**
* Convert Driver::Format to Framebuffer::Mode::Format * Convert Driver::Format to Framebuffer::Mode::Format
@ -75,18 +76,27 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Framebuffer::Se
** Framebuffer::Session interface ** ** Framebuffer::Session interface **
************************************/ ************************************/
Dataspace_capability dataspace() { return _ds; } Dataspace_capability dataspace() override { return _ds; }
Mode mode() const Mode mode() const override
{ {
return Mode(_width, return Mode(_width,
_height, _height,
_convert_format(_format)); _convert_format(_format));
} }
void mode_sigh(Genode::Signal_context_capability) { } void mode_sigh(Genode::Signal_context_capability) override { }
void refresh(int, int, int, int) { } void sync_sigh(Genode::Signal_context_capability sigh) override
{
_sync_sigh = sigh;
}
void refresh(int, int, int, int) override
{
if (_sync_sigh.valid())
Signal_transmitter(_sync_sigh).submit();
}
}; };

View File

@ -60,6 +60,7 @@ namespace Framebuffer
Genode::addr_t _regs_base; Genode::addr_t _regs_base;
Genode::addr_t _sys_regs_base; Genode::addr_t _sys_regs_base;
Timer::Connection _timer; Timer::Connection _timer;
Genode::Signal_context_capability _sync_sigh;
enum { enum {
/** /**
@ -155,13 +156,19 @@ namespace Framebuffer
reg_write(PL11X_REG_CTRL, ctrl | CTRL_POWER); reg_write(PL11X_REG_CTRL, ctrl | CTRL_POWER);
} }
Genode::Dataspace_capability dataspace() { return _fb_ds_cap; } Genode::Dataspace_capability dataspace() override { return _fb_ds_cap; }
Mode mode() const { return Mode(SCR_WIDTH, SCR_HEIGHT, Mode::RGB565); } Mode mode() const override { return Mode(SCR_WIDTH, SCR_HEIGHT, Mode::RGB565); }
void mode_sigh(Genode::Signal_context_capability) { } void mode_sigh(Genode::Signal_context_capability) override { }
void refresh(int x, int y, int w, int h) { } void sync_sigh(Genode::Signal_context_capability sigh) override { _sync_sigh = sigh; }
void refresh(int x, int y, int w, int h) override
{
if (_sync_sigh.valid())
Genode::Signal_transmitter(_sync_sigh).submit();
}
}; };
@ -175,7 +182,7 @@ namespace Framebuffer
protected: protected:
Session_component *_create_session(const char *args) { Session_component *_create_session(const char *args) override {
return new (md_alloc()) Session_component(_lcd_regs_base, return new (md_alloc()) Session_component(_lcd_regs_base,
_sys_regs_base, _sys_regs_base,
_fb_ds_cap); } _fb_ds_cap); }

View File

@ -33,6 +33,7 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Framebuffer::Se
size_t const _width; size_t const _width;
size_t const _height; size_t const _height;
Attached_io_mem_dataspace _fb_mem; Attached_io_mem_dataspace _fb_mem;
Signal_context_capability _sync_sigh;
public: public:
@ -45,16 +46,25 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Framebuffer::Se
** Framebuffer::Session interface ** ** Framebuffer::Session interface **
************************************/ ************************************/
Dataspace_capability dataspace() { return _fb_mem.cap(); } Dataspace_capability dataspace() override { return _fb_mem.cap(); }
Mode mode() const Mode mode() const override
{ {
return Mode(_width, _height, Mode::RGB565); return Mode(_width, _height, Mode::RGB565);
} }
void mode_sigh(Genode::Signal_context_capability) { } void mode_sigh(Genode::Signal_context_capability) override { }
void refresh(int, int, int, int) { } void sync_sigh(Genode::Signal_context_capability sigh) override
{
_sync_sigh = sigh;
}
void refresh(int, int, int, int) override
{
if (_sync_sigh.valid())
Signal_transmitter(_sync_sigh).submit();
}
}; };

View File

@ -52,6 +52,8 @@ namespace Framebuffer {
Mode _mode; Mode _mode;
Genode::Signal_context_capability _sync_sigh;
public: public:
/** /**
@ -59,13 +61,18 @@ namespace Framebuffer {
*/ */
Session_component() : _mode(scr_width, scr_height, Mode::RGB565) { } Session_component() : _mode(scr_width, scr_height, Mode::RGB565) { }
Genode::Dataspace_capability dataspace() { return fb_ds_cap; } Genode::Dataspace_capability dataspace() override { return fb_ds_cap; }
Mode mode() const { return _mode; } Mode mode() const override { return _mode; }
void mode_sigh(Genode::Signal_context_capability) { } void mode_sigh(Genode::Signal_context_capability) override { }
void refresh(int x, int y, int w, int h) void sync_sigh(Genode::Signal_context_capability sigh) override
{
_sync_sigh = sigh;
}
void refresh(int x, int y, int w, int h) override
{ {
/* clip refresh area to screen boundaries */ /* clip refresh area to screen boundaries */
int x1 = Genode::max(x, 0); int x1 = Genode::max(x, 0);
@ -73,7 +80,7 @@ namespace Framebuffer {
int x2 = Genode::min(x + w - 1, scr_width - 1); int x2 = Genode::min(x + w - 1, scr_width - 1);
int y2 = Genode::min(y + h - 1, scr_height - 1); int y2 = Genode::min(y + h - 1, scr_height - 1);
if (x1 > x2 || y1 > y2) return; if (x1 <= x2 && y1 <= y2) {
/* copy pixels from shared dataspace to sdl surface */ /* copy pixels from shared dataspace to sdl surface */
const int start_offset = _mode.bytes_per_pixel()*(y1*scr_width + x1); const int start_offset = _mode.bytes_per_pixel()*(y1*scr_width + x1);
@ -89,6 +96,10 @@ namespace Framebuffer {
/* flush pixels in sdl window */ /* flush pixels in sdl window */
SDL_UpdateRect(screen, x1, y1, x2 - x1 + 1, y2 - y1 + 1); SDL_UpdateRect(screen, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
} }
if (_sync_sigh.valid())
Genode::Signal_transmitter(_sync_sigh).submit();
}
}; };
@ -102,7 +113,7 @@ namespace Framebuffer {
{ {
protected: protected:
Session_component *_create_session(const char *args) { Session_component *_create_session(const char *args) override {
return new (md_alloc()) Session_component(); } return new (md_alloc()) Session_component(); }
public: public:

View File

@ -311,6 +311,7 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Session>
Canvas_accessor &_canvas_accessor; Canvas_accessor &_canvas_accessor;
Buffer_provider &_buffer_provider; Buffer_provider &_buffer_provider;
Signal_context_capability _mode_sigh; Signal_context_capability _mode_sigh;
Signal_context_capability _sync_sigh;
Framebuffer::Mode _mode; Framebuffer::Mode _mode;
bool _alpha = false; bool _alpha = false;
@ -362,24 +363,26 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Session>
** Framebuffer::Session interface ** ** Framebuffer::Session interface **
************************************/ ************************************/
Dataspace_capability dataspace() Dataspace_capability dataspace() override
{ {
_buffer = _buffer_provider.realloc_buffer(_mode, _alpha); _buffer = _buffer_provider.realloc_buffer(_mode, _alpha);
return _buffer ? _buffer->ds_cap() : Genode::Ram_dataspace_capability(); return _buffer ? _buffer->ds_cap() : Genode::Ram_dataspace_capability();
} }
Mode mode() const Mode mode() const override { return _mode; }
void mode_sigh(Signal_context_capability sigh) override
{ {
return _mode; _mode_sigh = sigh;
} }
void mode_sigh(Signal_context_capability mode_sigh) void sync_sigh(Signal_context_capability sigh) override
{ {
_mode_sigh = mode_sigh; _sync_sigh = sigh;
} }
void refresh(int x, int y, int w, int h) void refresh(int x, int y, int w, int h) override
{ {
_view_stack.update_session_views(_canvas(), _session, _view_stack.update_session_views(_canvas(), _session,
Rect(Point(x, y), Area(w, h))); Rect(Point(x, y), Area(w, h)));
@ -391,6 +394,9 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Session>
_flush_merger.reset(); _flush_merger.reset();
} }
_flush_merger.defer = true; _flush_merger.defer = true;
if (_sync_sigh.valid())
Signal_transmitter(_sync_sigh).submit();
} }
}; };

View File

@ -76,6 +76,12 @@ namespace Framebuffer {
} }
void Session_component::sync_sigh(Genode::Signal_context_capability sigh_cap)
{
_framebuffer.sync_sigh(sigh_cap);
}
void Session_component::refresh(int x, int y, int w, int h) void Session_component::refresh(int x, int y, int w, int h)
{ {
_framebuffer.refresh(x, y, w, h); _framebuffer.refresh(x, y, w, h);

View File

@ -45,10 +45,11 @@ namespace Framebuffer {
int max_width = 0, int max_width = 0,
int max_height = 0); int max_height = 0);
Genode::Dataspace_capability dataspace(); Genode::Dataspace_capability dataspace() override;
Mode mode() const; Mode mode() const override;
void mode_sigh(Genode::Signal_context_capability sigh_cap); void mode_sigh(Genode::Signal_context_capability) override;
void refresh(int x, int y, int w, int h); void sync_sigh(Genode::Signal_context_capability) override;
void refresh(int, int, int, int) override;
}; };
} }