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;
Genode::Signal_context_capability _sync_sigh;
public:
Session_component(Window_content &window_content)
: _window_content(window_content) { }
Genode::Dataspace_capability dataspace()
Genode::Dataspace_capability dataspace() override
{
_window_content.realloc_framebuffer();
return _window_content.fb_ds_cap();
}
Mode mode() const
Mode mode() const override
{
return Mode(_window_content.mode_size().w(),
_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); }
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);
if (_sync_sigh.valid())
Genode::Signal_transmitter(_sync_sigh).submit();
}
};
@ -311,7 +319,7 @@ namespace Framebuffer
protected:
Session_component *_create_session(const char *args) {
Session_component *_create_session(const char *args) override {
return new (md_alloc()) Session_component(_window_content); }
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)
{
_framebuffer.refresh(x, y, w, h);

View File

@ -45,10 +45,11 @@ namespace Framebuffer {
int max_width = 0,
int max_height = 0);
Genode::Dataspace_capability dataspace();
Mode mode() const;
void mode_sigh(Genode::Signal_context_capability sigh_cap);
void refresh(int x, int y, int w, int h);
Genode::Dataspace_capability dataspace() override;
Mode mode() const override;
void mode_sigh(Genode::Signal_context_capability) override;
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;
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:
/**
@ -146,43 +170,30 @@ namespace Framebuffer {
** Framebuffer session interface **
***********************************/
Dataspace_capability dataspace() {
Dataspace_capability dataspace() override {
return _buffered ? Dataspace_capability(_bb_ds)
: Dataspace_capability(_fb_ds); }
void release() { }
Mode mode() const
Mode mode() const override
{
return Mode(_scr_width, _scr_height,
_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 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 */
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;
void refresh(int x, int y, int w, int h) override
{
if (_buffered)
_refresh_buffered(x, y, w, h);
/* 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);
if (_sync_sigh.valid())
Signal_transmitter(_sync_sigh).submit();
}
};
@ -196,7 +207,7 @@ namespace Framebuffer {
{
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),
scr_height = session_arg("height", args, "fb_height", 768),

View File

@ -24,15 +24,18 @@ namespace Framebuffer {
explicit Session_client(Session_capability session)
: Genode::Rpc_client<Session>(session) { }
Genode::Dataspace_capability dataspace() {
Genode::Dataspace_capability dataspace() override {
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); }
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); }
};
}

View File

@ -105,6 +105,11 @@ namespace Framebuffer {
*/
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 **
@ -114,8 +119,10 @@ namespace Framebuffer {
GENODE_RPC(Rpc_mode, Mode, mode);
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_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)
: Genode::Rpc_client<Imx_session>(session) { }
Genode::Dataspace_capability dataspace() {
Genode::Dataspace_capability dataspace() override {
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); }
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); }
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); }
};
}

View File

@ -39,12 +39,13 @@ class Framebuffer::Session_component
{
private:
size_t _width;
size_t _height;
Driver::Format _format;
size_t _size;
Dataspace_capability _ds;
addr_t _phys_base;
size_t _width;
size_t _height;
Driver::Format _format;
size_t _size;
Dataspace_capability _ds;
addr_t _phys_base;
Signal_context_capability _sync_sigh;
/**
* Convert Driver::Format to Framebuffer::Mode::Format
@ -88,16 +89,25 @@ class Framebuffer::Session_component
** 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));
}
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;
void *_fb_addr;
Signal_context_capability _sync_sigh;
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:
Session_component(Driver &driver, bool buffered)
@ -68,29 +89,22 @@ class Framebuffer::Session_component :
** Framebuffer::session interface **
**************************************/
Dataspace_capability dataspace() { return _buffered ? _bb_ds : _fb_ds; }
Mode mode() const { return _mode; }
void mode_sigh(Genode::Signal_context_capability) { }
Dataspace_capability dataspace() override { return _buffered ? _bb_ds : _fb_ds; }
Mode mode() const override { return _mode; }
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 */
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;
void refresh(int x, int y, int w, int h) override
{
if (_buffered)
_refresh_buffered(x, y, w, h);
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);
if (_sync_sigh.valid())
Signal_transmitter(_sync_sigh).submit();
}
void overlay(Genode::addr_t phys_base, int x, int y, int alpha) {

View File

@ -36,10 +36,11 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Framebuffer::Se
size_t _width;
size_t _height;
Driver::Format _format;
size_t _size;
Dataspace_capability _ds;
addr_t _phys_base;
Driver::Format _format;
size_t _size;
Dataspace_capability _ds;
addr_t _phys_base;
Signal_context_capability _sync_sigh;
/**
* Convert Driver::Format to Framebuffer::Mode::Format
@ -75,18 +76,27 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Framebuffer::Se
** 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));
}
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

@ -55,11 +55,12 @@ namespace Framebuffer
{
private:
Genode::Dataspace_capability _fb_ds_cap;
Genode::Dataspace_client _fb_ds;
Genode::addr_t _regs_base;
Genode::addr_t _sys_regs_base;
Timer::Connection _timer;
Genode::Dataspace_capability _fb_ds_cap;
Genode::Dataspace_client _fb_ds;
Genode::addr_t _regs_base;
Genode::addr_t _sys_regs_base;
Timer::Connection _timer;
Genode::Signal_context_capability _sync_sigh;
enum {
/**
@ -155,13 +156,19 @@ namespace Framebuffer
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:
Session_component *_create_session(const char *args) {
Session_component *_create_session(const char *args) override {
return new (md_alloc()) Session_component(_lcd_regs_base,
_sys_regs_base,
_fb_ds_cap); }

View File

@ -30,9 +30,10 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Framebuffer::Se
{
private:
size_t const _width;
size_t const _height;
size_t const _width;
size_t const _height;
Attached_io_mem_dataspace _fb_mem;
Signal_context_capability _sync_sigh;
public:
@ -45,16 +46,25 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Framebuffer::Se
** 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);
}
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;
Genode::Signal_context_capability _sync_sigh;
public:
/**
@ -59,13 +61,18 @@ namespace Framebuffer {
*/
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 */
int x1 = Genode::max(x, 0);
@ -73,21 +80,25 @@ namespace Framebuffer {
int x2 = Genode::min(x + w - 1, scr_width - 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 */
const int start_offset = _mode.bytes_per_pixel()*(y1*scr_width + x1);
const int line_len = _mode.bytes_per_pixel()*(x2 - x1 + 1);
const int pitch = _mode.bytes_per_pixel()*scr_width;
/* copy pixels from shared dataspace to sdl surface */
const int start_offset = _mode.bytes_per_pixel()*(y1*scr_width + x1);
const int line_len = _mode.bytes_per_pixel()*(x2 - x1 + 1);
const int pitch = _mode.bytes_per_pixel()*scr_width;
char *src = (char *)fb_ds_addr + start_offset;
char *dst = (char *)screen->pixels + start_offset;
char *src = (char *)fb_ds_addr + start_offset;
char *dst = (char *)screen->pixels + start_offset;
for (int i = y1; i <= y2; i++, src += pitch, dst += pitch)
Genode::memcpy(dst, src, line_len);
for (int i = y1; i <= y2; i++, src += pitch, dst += pitch)
Genode::memcpy(dst, src, line_len);
/* flush pixels in sdl window */
SDL_UpdateRect(screen, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
/* flush pixels in sdl window */
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:
Session_component *_create_session(const char *args) {
Session_component *_create_session(const char *args) override {
return new (md_alloc()) Session_component(); }
public:

View File

@ -311,6 +311,7 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Session>
Canvas_accessor &_canvas_accessor;
Buffer_provider &_buffer_provider;
Signal_context_capability _mode_sigh;
Signal_context_capability _sync_sigh;
Framebuffer::Mode _mode;
bool _alpha = false;
@ -362,24 +363,26 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Session>
** Framebuffer::Session interface **
************************************/
Dataspace_capability dataspace()
Dataspace_capability dataspace() override
{
_buffer = _buffer_provider.realloc_buffer(_mode, _alpha);
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,
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.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)
{
_framebuffer.refresh(x, y, w, h);

View File

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