diff --git a/demo/src/app/backdrop/main.cc b/demo/src/app/backdrop/main.cc index 8548a39905..ec6e2797f3 100644 --- a/demo/src/app/backdrop/main.cc +++ b/demo/src/app/backdrop/main.cc @@ -232,14 +232,18 @@ int main(int argc, char **argv) return -2; } - static Nitpicker::Connection nitpicker; + static Nitpicker::Connection nitpicker; + + /* obtain physical screen size */ + Framebuffer::Mode const mode = nitpicker.mode(); + + /* setup virtual framebuffer mode */ + nitpicker.buffer(mode, false); + static Framebuffer::Session_client framebuffer(nitpicker.framebuffer_session()); Nitpicker::View_capability view_cap = nitpicker.create_view(); static Nitpicker::View_client view(view_cap); - /* obtain screen size */ - Framebuffer::Mode const mode = framebuffer.mode(); - if (mode.format() != Framebuffer::Mode::RGB565) { printf("Error: Color mode %d not supported\n", (int)mode.format()); return -3; diff --git a/demo/src/app/scout/genode/platform_genode.cc b/demo/src/app/scout/genode/platform_genode.cc index f74b9bd89c..2fb14d1d7e 100644 --- a/demo/src/app/scout/genode/platform_genode.cc +++ b/demo/src/app/scout/genode/platform_genode.cc @@ -215,28 +215,19 @@ Platform::Platform(unsigned vx, unsigned vy, unsigned vw, unsigned vh, Config::browser_attr = 7; /* - * Create temporary nitpicker session just to determine the screen size - * - * NOTE: This approach has the disadvantage creating the nitpicker session - * is not an atomic operation. In theory, both session requests may be - * propagated to different nitpicker instances. + * Allocate a nitpicker buffer double as high as the physical screen to + * use the upper/lower halves for double-buffering. */ - _nitpicker = new (env()->heap()) Nitpicker::Connection(); - Framebuffer::Mode const query_mode = _nitpicker->framebuffer()->mode(); + _nitpicker = new (env()->heap()) Nitpicker::Connection; + Framebuffer::Mode const query_mode = _nitpicker->mode(); _scr_w = query_mode.width(); _scr_h = query_mode.height(); _scr_format = query_mode.format(); - destroy(env()->heap(), _nitpicker); if (_max_vw) _scr_w = min(_max_vw, _scr_w); if (_max_vh) _scr_h = min(_max_vh, _scr_h); - /* - * Allocate a nitpicker buffer double as high as the physical screen to - * use the upper/lower halves for double-buffering. - */ - _nitpicker = new (env()->heap()) - Nitpicker::Connection(_scr_w, _scr_h*2, false, _scr_format); + _nitpicker->buffer(Framebuffer::Mode(_scr_w, _scr_h*2, _scr_format), false); static Timer::Connection timer; _timer = &timer; diff --git a/demo/src/server/nitlog/main.cc b/demo/src/server/nitlog/main.cc index e327a8c62e..b4d00719d6 100644 --- a/demo/src/server/nitlog/main.cc +++ b/demo/src/server/nitlog/main.cc @@ -342,9 +342,11 @@ int main(int argc, char **argv) int log_win_h = default_font.str_h(" ") * LOG_H + 2; /* init sessions to the required external services */ - static Nitpicker::Connection nitpicker(log_win_w, log_win_h); + static Nitpicker::Connection nitpicker; static Timer::Connection timer; + nitpicker.buffer(Framebuffer::Mode(LOG_W, LOG_H, Framebuffer::Mode::RGB565), false); + /* initialize entry point that serves the root interface */ enum { STACK_SIZE = 4096 }; static Cap_connection cap; diff --git a/libports/src/app/qt5/qt_avplay/framebuffer_session_component.cc b/libports/src/app/qt5/qt_avplay/framebuffer_session_component.cc index f12b48ad5a..ea97849bcf 100644 --- a/libports/src/app/qt5/qt_avplay/framebuffer_session_component.cc +++ b/libports/src/app/qt5/qt_avplay/framebuffer_session_component.cc @@ -41,11 +41,14 @@ namespace Framebuffer { QNitpickerViewWidget &nitpicker_view_widget, int max_width, int max_height) - : _nitpicker(Nitpicker::Connection( - _limited_size(session_arg(args, "fb_width"), max_width), - _limited_size(session_arg(args, "fb_height"), max_height))), + : _framebuffer(_nitpicker.framebuffer_session()) { + Framebuffer::Mode const + mode(_limited_size(session_arg(args, "fb_width"), max_width), + _limited_size(session_arg(args, "fb_height"), max_height), + _nitpicker.mode().format()); + _nitpicker.buffer(mode, false); Nitpicker::View_capability nitpicker_view_cap = _nitpicker.create_view(); Mode _mode = _framebuffer.mode(); nitpicker_view_widget.setNitpickerView(nitpicker_view_cap, diff --git a/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerscreen.h b/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerscreen.h index f58011eb90..05d98e7c54 100644 --- a/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerscreen.h +++ b/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerscreen.h @@ -38,7 +38,8 @@ class QNitpickerScreen : public QPlatformScreen QNitpickerScreen() : _framebuffer(_nitpicker.framebuffer_session()) { - Framebuffer::Mode const scr_mode = _framebuffer.mode(); + Framebuffer::Mode const scr_mode = _nitpicker.mode(); + _nitpicker.buffer(scr_mode, false); if (scr_mode.format() != Framebuffer::Mode::RGB565) qCritical() << "Nitpicker screen format is not RGB565"; diff --git a/os/include/nitpicker_session/client.h b/os/include/nitpicker_session/client.h index 07523db716..ef10e53cda 100644 --- a/os/include/nitpicker_session/client.h +++ b/os/include/nitpicker_session/client.h @@ -17,28 +17,34 @@ #include #include -namespace Nitpicker { +namespace Nitpicker { struct Session_client; } - struct Session_client : public Genode::Rpc_client - { - explicit Session_client(Session_capability session) - : Genode::Rpc_client(session) { } - Framebuffer::Session_capability framebuffer_session() { - return call(); } +struct Nitpicker::Session_client : public Rpc_client +{ + explicit Session_client(Session_capability session) + : Rpc_client(session) { } - Input::Session_capability input_session() { - return call(); } + Framebuffer::Session_capability framebuffer_session() { + return call(); } - View_capability create_view() { - return call(); } + Input::Session_capability input_session() { + return call(); } - void destroy_view(View_capability view) { - call(view); } + View_capability create_view() { + return call(); } - int background(View_capability view) { - return call(view); } - }; -} + void destroy_view(View_capability view) { + call(view); } + + int background(View_capability view) { + return call(view); } + + Framebuffer::Mode mode() { + return call(); } + + void buffer(Framebuffer::Mode mode, bool alpha) { + call(mode, alpha); } +}; #endif /* _INCLUDE__NITPICKER_SESSION__CLIENT_H_ */ diff --git a/os/include/nitpicker_session/connection.h b/os/include/nitpicker_session/connection.h index bffe797623..e45571edb9 100644 --- a/os/include/nitpicker_session/connection.h +++ b/os/include/nitpicker_session/connection.h @@ -20,108 +20,76 @@ #include #include -namespace Nitpicker { +namespace Nitpicker { class Connection; } - class Connection : public Genode::Connection, - public Session_client - { - private: - Framebuffer::Session_client _framebuffer; - Input::Session_client _input; +class Nitpicker::Connection : public Genode::Connection, + public Session_client +{ + private: - /** - * Create session and return typed session capability + Framebuffer::Session_client _framebuffer; + Input::Session_client _input; + + /** + * Create session and return typed session capability + */ + Session_capability _connect(bool stay_top) + { + enum { ARGBUF_SIZE = 128 }; + char argbuf[ARGBUF_SIZE]; + argbuf[0] = 0; + + /* + * Declare ram-quota donation */ - Session_capability - _connect(unsigned width, unsigned height, bool alpha, - Framebuffer::Mode::Format format, bool stay_top) - { - using namespace Genode; + enum { SESSION_METADATA = 20*1024 }; + Arg_string::set_arg(argbuf, sizeof(argbuf), "ram_quota", SESSION_METADATA); - enum { ARGBUF_SIZE = 128 }; - char argbuf[ARGBUF_SIZE]; - argbuf[0] = 0; + if (stay_top) + Arg_string::set_arg(argbuf, sizeof(argbuf), "stay_top", "yes"); - /* by default, donate as much as needed for a 1024x768 RGB565 screen */ - Genode::size_t ram_quota = 1600*1024; + return session(argbuf); + } - /* - * NOTE: When specifying an INVALID mode as argument, we could - * probe for any valid video mode. For now, we just probe for - * RGB565. - */ - if (format == Framebuffer::Mode::INVALID) - format = Framebuffer::Mode::RGB565; + public: - /* if buffer dimensions are specified, calculate ram quota to donate */ - if (width && height) - ram_quota = width*height*Framebuffer::Mode::bytes_per_pixel(format); + /** + * Constructor + */ + Connection(bool stay_top = false) + : + /* establish nitpicker session */ + Genode::Connection(_connect(stay_top)), + Session_client(cap()), - /* account for alpha and input-mask buffers */ - if (alpha) - ram_quota += width*height*2; + /* request frame-buffer and input sub sessions */ + _framebuffer(framebuffer_session()), + _input(input_session()) + { } - /* add quota for storing server-side meta data */ - enum { SESSION_METADATA = 16*1024 }; - ram_quota += SESSION_METADATA; + void buffer(Framebuffer::Mode mode, bool use_alpha) + { + enum { ARGBUF_SIZE = 128 }; + char argbuf[ARGBUF_SIZE]; + argbuf[0] = 0; - /* declare ram-quota donation */ - Arg_string::set_arg(argbuf, sizeof(argbuf), "ram_quota", ram_quota); + Arg_string::set_arg(argbuf, sizeof(argbuf), "ram_quota", + ram_quota(mode, use_alpha)); - /* set optional session-constructor arguments */ - if (width) - Arg_string::set_arg(argbuf, sizeof(argbuf), "fb_width", width); - if (height) - Arg_string::set_arg(argbuf, sizeof(argbuf), "fb_height", height); - if (format != Framebuffer::Mode::INVALID) - Arg_string::set_arg(argbuf, sizeof(argbuf), "fb_format", format); - if (alpha) - Arg_string::set_arg(argbuf, sizeof(argbuf), "alpha", "yes"); - if (stay_top) - Arg_string::set_arg(argbuf, sizeof(argbuf), "stay_top", "yes"); + env()->parent()->upgrade(cap(), argbuf); + Session_client::buffer(mode, use_alpha); + } - return session(argbuf); - } + /** + * Return sub session for Nitpicker's input service + */ + Input::Session *input() { return &_input; } - public: - - /** - * Constructor - * - * \param width desired buffer width - * \param height desired buffer height - * \param alpha true for using a buffer with alpha channel - * \param format desired pixel format - * - * The specified value for 'format' is not enforced. After creating - * the session, you should validate the actual pixel format of the - * buffer by its 'mode'. - */ - Connection(unsigned width = 0, unsigned height = 0, bool alpha = false, - Framebuffer::Mode::Format format = Framebuffer::Mode::INVALID, - bool stay_top = false) - : - /* establish nitpicker session */ - Genode::Connection(_connect(width, height, alpha, - format, stay_top)), - Session_client(cap()), - - /* request frame-buffer and input sub sessions */ - _framebuffer(framebuffer_session()), - _input(input_session()) - { } - - /** - * Return sub session for Nitpicker's input service - */ - Input::Session *input() { return &_input; } - - /** - * Return sub session for session's frame buffer - */ - Framebuffer::Session *framebuffer() { return &_framebuffer; } - }; -} + /** + * Return sub session for session's frame buffer + */ + Framebuffer::Session *framebuffer() { return &_framebuffer; } +}; #endif /* _INCLUDE__NITPICKER_SESSION__CONNECTION_H_ */ diff --git a/os/include/nitpicker_session/nitpicker_session.h b/os/include/nitpicker_session/nitpicker_session.h index a636bfd3e9..8cc62c83a0 100644 --- a/os/include/nitpicker_session/nitpicker_session.h +++ b/os/include/nitpicker_session/nitpicker_session.h @@ -22,54 +22,91 @@ #include namespace Nitpicker { - - struct Session : Genode::Session - { - static const char *service_name() { return "Nitpicker"; } - - virtual ~Session() { } - - /** - * Request framebuffer sub-session - */ - virtual Framebuffer::Session_capability framebuffer_session() = 0; - - /** - * Request input sub-session - */ - virtual Input::Session_capability input_session() = 0; - - /** - * Create a new view at the buffer - * - * \return capability to a new view - */ - virtual View_capability create_view() = 0; - - /** - * Destroy view - */ - virtual void destroy_view(View_capability view) = 0; - - /** - * Define view that is used as desktop background - */ - virtual int background(View_capability view) = 0; - - - /********************* - ** RPC declaration ** - *********************/ - - GENODE_RPC(Rpc_framebuffer_session, Framebuffer::Session_capability, framebuffer_session); - GENODE_RPC(Rpc_input_session, Input::Session_capability, input_session); - GENODE_RPC(Rpc_create_view, View_capability, create_view); - GENODE_RPC(Rpc_destroy_view, void, destroy_view, View_capability); - GENODE_RPC(Rpc_background, int, background, View_capability); - - GENODE_RPC_INTERFACE(Rpc_framebuffer_session, Rpc_input_session, - Rpc_create_view, Rpc_destroy_view, Rpc_background); - }; + using namespace Genode; + struct Session; } + +struct Nitpicker::Session : Genode::Session +{ + static const char *service_name() { return "Nitpicker"; } + + /** + * Exception type + */ + struct Out_of_metadata : Genode::Exception { }; + + virtual ~Session() { } + + /** + * Request framebuffer sub-session + */ + virtual Framebuffer::Session_capability framebuffer_session() = 0; + + /** + * Request input sub-session + */ + virtual Input::Session_capability input_session() = 0; + + /** + * Create a new view at the buffer + * + * \return capability to a new view + */ + virtual View_capability create_view() = 0; + + /** + * Destroy view + */ + virtual void destroy_view(View_capability view) = 0; + + /** + * Define view that is used as desktop background + */ + virtual int background(View_capability view) = 0; + + /** + * Return physical screen mode + */ + virtual Framebuffer::Mode mode() = 0; + + /** + * Define dimensions of virtual framebuffer + * + * \throw Out_of_metadata session quota does not suffice for specified + * buffer dimensions + */ + virtual void buffer(Framebuffer::Mode mode, bool use_alpha) = 0; + + /** + * Return number of bytes needed for virtual framebuffer of specified size + */ + static size_t ram_quota(Framebuffer::Mode mode, bool use_alpha) + { + /* + * If alpha blending is used, each pixel requires an additional byte + * for the alpha value and a byte holding the input mask. + */ + return (mode.bytes_per_pixel() + 2*use_alpha)*mode.width()*mode.height(); + } + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_framebuffer_session, Framebuffer::Session_capability, framebuffer_session); + GENODE_RPC(Rpc_input_session, Input::Session_capability, input_session); + GENODE_RPC(Rpc_create_view, View_capability, create_view); + GENODE_RPC(Rpc_destroy_view, void, destroy_view, View_capability); + GENODE_RPC(Rpc_background, int, background, View_capability); + GENODE_RPC(Rpc_mode, Framebuffer::Mode, mode); + GENODE_RPC_THROW(Rpc_buffer, void, buffer, GENODE_TYPE_LIST(Out_of_metadata), + Framebuffer::Mode, bool); + + GENODE_RPC_INTERFACE(Rpc_framebuffer_session, Rpc_input_session, + Rpc_create_view, Rpc_destroy_view, Rpc_background, + Rpc_mode, Rpc_buffer); +}; + #endif /* _INCLUDE__NITPICKER_SESSION__NITPICKER_SESSION_H_ */ diff --git a/os/src/app/xvfb/main.cc b/os/src/app/xvfb/main.cc index 22bf604421..3cc4adea90 100644 --- a/os/src/app/xvfb/main.cc +++ b/os/src/app/xvfb/main.cc @@ -60,8 +60,16 @@ static Pixel *fb_addr; static Nitpicker::Session *nitpicker() { - static Nitpicker::Connection nitpicker_connection; - return &nitpicker_connection; + struct Connection : Nitpicker::Connection + { + Connection() + { + Nitpicker::Connection::buffer(mode(), false); + } + }; + + static Connection connection; + return &connection; } diff --git a/os/src/app/xvfb/target.mk b/os/src/app/xvfb/target.mk index d456edf93d..4429cc0f05 100644 --- a/os/src/app/xvfb/target.mk +++ b/os/src/app/xvfb/target.mk @@ -1,6 +1,6 @@ TARGET = xvfb REQUIRES = linux x11 xtest xdamage SRC_CC = main.cc inject_input.cc -LIBS = base_hybrid syscall blit xev_track config +LIBS = lx_hybrid syscall blit xev_track config EXT_OBJECTS += -lX11 -lXdamage /usr/lib/libXtst.so.6 diff --git a/os/src/server/loader/nitpicker.h b/os/src/server/loader/nitpicker.h index 571431f56c..b892179512 100644 --- a/os/src/server/loader/nitpicker.h +++ b/os/src/server/loader/nitpicker.h @@ -161,8 +161,6 @@ namespace Nitpicker { Rpc_entrypoint &_ep; - int _fb_width, _fb_height; - Nitpicker::Connection _nitpicker; View_capability _nitpicker_view; @@ -189,13 +187,6 @@ namespace Nitpicker { : _ep(ep), - /* store the framebuffer size for view size constraining */ - _fb_width(_session_arg(args, "fb_width")), - _fb_height(_session_arg(args, "fb_height")), - - /* connect to the "real" Nitpicker service */ - _nitpicker(_fb_width, _fb_height), - /* create Nitpicker view */ _nitpicker_view(_nitpicker.create_view()), @@ -242,6 +233,16 @@ namespace Nitpicker { return 0; } + Framebuffer::Mode mode() + { + return _nitpicker.mode(); + } + + void buffer(Framebuffer::Mode mode, bool use_alpha) + { + _nitpicker.buffer(mode, use_alpha); + } + /********************************** ** Input::Transformer interface ** @@ -270,9 +271,11 @@ namespace Nitpicker { */ Loader::Session::View_geometry loader_view_geometry() { + Framebuffer::Session_client framebuffer(framebuffer_session()); + Framebuffer::Mode const mode = framebuffer.mode(); Loader::Session::View_geometry result( - min(_proxy_view.w(), _fb_width), - min(_proxy_view.h(), _fb_height), + min(_proxy_view.w(), mode.width()), + min(_proxy_view.h(), mode.height()), _proxy_view.buf_x(), _proxy_view.buf_y()); diff --git a/os/src/server/nit_fb/main.cc b/os/src/server/nit_fb/main.cc index 702eb5cc9a..b1bc2e59d1 100644 --- a/os/src/server/nit_fb/main.cc +++ b/os/src/server/nit_fb/main.cc @@ -149,17 +149,22 @@ int main(int argc, char **argv) /* * Open Nitpicker session */ - static Nitpicker::Connection nitpicker(view_w, view_h); + static Nitpicker::Connection nitpicker; /* * If no config was provided, use screen size of Nitpicker */ if (view_w == 0 || view_h == 0) { - Framebuffer::Session_client nit_fb(nitpicker.framebuffer_session()); - Framebuffer::Mode const mode = nit_fb.mode(); + Framebuffer::Mode const mode = nitpicker.mode(); view_w = mode.width(), view_h = mode.height(); } + /* + * Setup virtual framebuffer + */ + Framebuffer::Mode const mode(view_w, view_h, Framebuffer::Mode::RGB565); + nitpicker.buffer(mode, false); + PINF("using xywh=(%ld,%ld,%ld,%ld) refresh_rate=%u", view_x, view_y, view_w, view_h, cfg.refresh_rate); diff --git a/os/src/server/nitpicker/background.h b/os/src/server/nitpicker/background.h index b7a8b1c18f..4959d2f8ee 100644 --- a/os/src/server/nitpicker/background.h +++ b/os/src/server/nitpicker/background.h @@ -28,7 +28,7 @@ struct Background : private Texture, Session, View */ Background(Area size) : - Texture(Area(0, 0)), Session(Genode::Session_label(""), *this, 0), + Texture(Area(0, 0)), Session(Genode::Session_label(""), 0, false), View(*this, View::NOT_STAY_TOP, View::NOT_TRANSPARENT, View::BACKGROUND, Rect(Point(0, 0), size)), color(25, 37, 50) diff --git a/os/src/server/nitpicker/chunky_menubar.h b/os/src/server/nitpicker/chunky_menubar.h index 2ea781649e..638cba97e9 100644 --- a/os/src/server/nitpicker/chunky_menubar.h +++ b/os/src/server/nitpicker/chunky_menubar.h @@ -30,9 +30,11 @@ class Chunky_menubar : public Chunky_texture, Chunky_menubar(PT *pixels, Area size) : Chunky_texture(pixels, 0, size), - Session(Genode::Session_label(""), *this, 0), + Session(Genode::Session_label(""), 0, false), Menubar(_chunky_canvas, size, *this), _chunky_canvas(pixels, size) - { } + { + Session::texture(this); + } /*********************** diff --git a/os/src/server/nitpicker/main.cc b/os/src/server/nitpicker/main.cc index 62824e89d0..31c287049d 100644 --- a/os/src/server/nitpicker/main.cc +++ b/os/src/server/nitpicker/main.cc @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -136,6 +137,18 @@ class Buffer }; +/** + * Interface for triggering the re-allocation of a virtual framebuffer + * + * Used by 'Framebuffer::Session_component', + * implemented by 'Nitpicker::Session_component' + */ +struct Buffer_provider +{ + virtual Buffer *realloc_buffer(Framebuffer::Mode mode, bool use_alpha) = 0; +}; + + template class Chunky_dataspace_texture : public Buffer, public Chunky_texture { @@ -263,37 +276,79 @@ class Framebuffer::Session_component : public Genode::Rpc_object { private: - ::Buffer &_buffer; - View_stack &_view_stack; - ::Session &_session; - Flush_merger &_flush_merger; - Framebuffer::Session &_framebuffer; + ::Buffer *_buffer = 0; + View_stack &_view_stack; + ::Session &_session; + Flush_merger &_flush_merger; + Framebuffer::Session &_framebuffer; + Buffer_provider &_buffer_provider; + Signal_context_capability _mode_sigh; + Framebuffer::Mode _mode; + bool _alpha = false; public: /** * Constructor - * - * \param session Nitpicker session */ - Session_component(::Buffer &buffer, View_stack &view_stack, - ::Session &session, Flush_merger &flush_merger, - Framebuffer::Session &framebuffer) + Session_component(View_stack &view_stack, + ::Session &session, + Flush_merger &flush_merger, + Framebuffer::Session &framebuffer, + Buffer_provider &buffer_provider) : - _buffer(buffer), _view_stack(view_stack), _session(session), - _flush_merger(flush_merger), _framebuffer(framebuffer) { } + _view_stack(view_stack), + _session(session), + _flush_merger(flush_merger), + _framebuffer(framebuffer), + _buffer_provider(buffer_provider) + { } - Dataspace_capability dataspace() { return _buffer.ds_cap(); } + + /** + * Change virtual framebuffer mode + * + * Called by Nitpicker::Session_component when re-dimensioning the + * buffer. + * + * The new mode does not immediately become active. The client can + * keep using an already obtained framebuffer dataspace. However, + * we inform the client about the mode change via a signal. If the + * client calls 'dataspace' the next time, the new mode becomes + * effective. + */ + void notify_mode_change(Framebuffer::Mode mode, bool alpha) + { + _mode = mode; + _alpha = alpha; + + if (_mode_sigh.valid()) + Signal_transmitter(_mode_sigh).submit(); + } + + + /************************************ + ** Framebuffer::Session interface ** + ************************************/ + + Dataspace_capability dataspace() + { + _buffer = _buffer_provider.realloc_buffer(_mode, _alpha); + + return _buffer ? _buffer->ds_cap() : Ram_dataspace_capability(); + } void release() { } Mode mode() const { - return Mode(_buffer.size().w(), _buffer.size().h(), - _buffer.format()); + return _mode; } - void mode_sigh(Signal_context_capability) { } + void mode_sigh(Signal_context_capability mode_sigh) + { + _mode_sigh = mode_sigh; + } void refresh(int x, int y, int w, int h) { @@ -378,10 +433,15 @@ class View_component : public Genode::List::Element, *****************************************/ class Nitpicker::Session_component : public Genode::Rpc_object, - public ::Session + public ::Session, + public Buffer_provider { private: + Allocator_guard _buffer_alloc; + + Framebuffer::Session &_framebuffer; + /* Framebuffer_session_component */ Framebuffer::Session_component _framebuffer_session_component; @@ -404,30 +464,57 @@ class Nitpicker::Session_component : public Genode::Rpc_object, bool const _provides_default_bg; + /* size of currently allocated virtual framebuffer, in bytes */ + size_t _buffer_size = 0; + + void _release_buffer() + { + if (!::Session::texture()) + return; + + typedef Pixel_rgb565 PT; + + /* retrieve pointer to texture from session */ + Chunky_dataspace_texture const *cdt = + static_cast const *>(::Session::texture()); + + ::Session::texture(0); + ::Session::input_mask(0); + + destroy(&_buffer_alloc, const_cast *>(cdt)); + + _buffer_alloc.upgrade(_buffer_size); + _buffer_size = 0; + } + public: /** * Constructor */ - Session_component(Session_label const &label, - ::Buffer &buffer, - Texture const &texture, - View_stack &view_stack, - Rpc_entrypoint &ep, - Flush_merger &flush_merger, - Framebuffer::Session &framebuffer, - int v_offset, - unsigned char const *input_mask, - bool provides_default_bg, - bool stay_top) + Session_component(Session_label const &label, + View_stack &view_stack, + Rpc_entrypoint &ep, + Flush_merger &flush_merger, + Framebuffer::Session &framebuffer, + int v_offset, + bool provides_default_bg, + bool stay_top, + Allocator &buffer_alloc, + size_t ram_quota) : - ::Session(label, texture, v_offset, input_mask, stay_top), - _framebuffer_session_component(buffer, view_stack, *this, flush_merger, framebuffer), + ::Session(label, v_offset, stay_top), + _buffer_alloc(&buffer_alloc, ram_quota), + _framebuffer(framebuffer), + _framebuffer_session_component(view_stack, *this, flush_merger, + framebuffer, *this), _ep(ep), _view_stack(view_stack), _framebuffer_session_cap(_ep.manage(&_framebuffer_session_component)), _input_session_cap(_ep.manage(&_input_session_component)), _provides_default_bg(provides_default_bg) - { } + { + _buffer_alloc.upgrade(ram_quota); + } /** * Destructor @@ -439,8 +526,12 @@ class Nitpicker::Session_component : public Genode::Rpc_object, while (View_component *vc = _view_list.first()) destroy_view(vc->cap()); + + _release_buffer(); } + void upgrade_ram_quota(size_t ram_quota) { _buffer_alloc.upgrade(ram_quota); } + /****************************************** ** Nitpicker-internal session interface ** @@ -517,6 +608,56 @@ class Nitpicker::Session_component : public Genode::Rpc_object, return 0; } + + Framebuffer::Mode mode() + { + unsigned const width = _framebuffer.mode().width(); + unsigned const height = _framebuffer.mode().height() + - ::Session::v_offset(); + + return Framebuffer::Mode(width, height, + _framebuffer.mode().format()); + } + + void buffer(Framebuffer::Mode mode, bool use_alpha) + { + /* check if the session quota suffices for the specified mode */ + if (_buffer_alloc.quota() < ram_quota(mode, use_alpha)) + throw Nitpicker::Session::Out_of_metadata(); + + _framebuffer_session_component.notify_mode_change(mode, use_alpha); + } + + + /******************************* + ** Buffer_provider interface ** + *******************************/ + + Buffer *realloc_buffer(Framebuffer::Mode mode, bool use_alpha) + { + _release_buffer(); + + Area const size(mode.width(), mode.height()); + + typedef Pixel_rgb565 PT; + + _buffer_size = + Chunky_dataspace_texture::calc_num_bytes(size, use_alpha); + + Chunky_dataspace_texture * const texture = + new (&_buffer_alloc) Chunky_dataspace_texture(size, use_alpha); + + if (!_buffer_alloc.withdraw(_buffer_size)) { + destroy(&_buffer_alloc, texture); + _buffer_size = 0; + return 0; + } + + ::Session::texture(texture); + ::Session::input_mask(texture->input_mask_buffer()); + + return texture; + } }; @@ -527,7 +668,7 @@ class Nitpicker::Root : public Genode::Root_component Session_list &_session_list; Global_keys &_global_keys; - Area _scr_size; + Framebuffer::Mode _scr_mode; View_stack &_view_stack; Flush_merger &_flush_merger; Framebuffer::Session &_framebuffer; @@ -542,17 +683,9 @@ class Nitpicker::Root : public Genode::Root_component int const v_offset = _default_v_offset; - /* determine buffer size of the session */ - Area const size(Arg_string::find_arg(args, "fb_width" ).long_value(_scr_size.w()), - Arg_string::find_arg(args, "fb_height").long_value(_scr_size.h() - v_offset)); - - bool const use_alpha = Arg_string::find_arg(args, "alpha").bool_value(false); bool const stay_top = Arg_string::find_arg(args, "stay_top").bool_value(false); - size_t const texture_num_bytes = Chunky_dataspace_texture::calc_num_bytes(size, use_alpha); - - size_t const required_quota = texture_num_bytes - + Input::Session_component::ev_ds_size(); + size_t const required_quota = Input::Session_component::ev_ds_size(); if (ram_quota < required_quota) { PWRN("Insufficient dontated ram_quota (%zd bytes), require %zd bytes", @@ -560,19 +693,16 @@ class Nitpicker::Root : public Genode::Root_component throw Root::Quota_exceeded(); } - /* allocate texture */ - Chunky_dataspace_texture * const cdt = - new (md_alloc()) Chunky_dataspace_texture(size, use_alpha); + size_t const unused_quota = ram_quota - required_quota; Session_label const label(args); bool const provides_default_bg = (strcmp(label.string(), "backdrop") == 0); Session_component *session = new (md_alloc()) - Session_component(Session_label(args), *cdt, *cdt, - _view_stack, *ep(), _flush_merger, - _framebuffer, v_offset, - cdt->input_mask_buffer(), - provides_default_bg, stay_top); + Session_component(Session_label(args), _view_stack, *ep(), + _flush_merger, _framebuffer, v_offset, + provides_default_bg, stay_top, + *md_alloc(), unused_quota); session->apply_session_color(); _session_list.insert(session); @@ -581,19 +711,18 @@ class Nitpicker::Root : public Genode::Root_component return session; } + void _upgrade_session(Session_component *s, const char *args) + { + size_t ram_quota = Arg_string::find_arg(args, "ram_quota").long_value(0); + s->upgrade_ram_quota(ram_quota); + } + void _destroy_session(Session_component *session) { - /* retrieve pointer to texture from session */ - Chunky_dataspace_texture const &cdt = - static_cast const &>(session->texture()); - _session_list.remove(session); _global_keys.apply_config(_session_list); destroy(md_alloc(), session); - - /* cast away constness just for destruction of the texture */ - destroy(md_alloc(), const_cast *>(&cdt)); } public: @@ -602,15 +731,15 @@ class Nitpicker::Root : public Genode::Root_component * Constructor */ Root(Session_list &session_list, Global_keys &global_keys, - Rpc_entrypoint &session_ep, Area scr_size, - View_stack &view_stack, Allocator &md_alloc, - Flush_merger &flush_merger, + Rpc_entrypoint &session_ep, View_stack &view_stack, + Allocator &md_alloc, Flush_merger &flush_merger, Framebuffer::Session &framebuffer, int default_v_offset) : Root_component(&session_ep, &md_alloc), _session_list(session_list), _global_keys(global_keys), - _scr_size(scr_size), _view_stack(view_stack), _flush_merger(flush_merger), - _framebuffer(framebuffer), _default_v_offset(default_v_offset) { } + _view_stack(view_stack), _flush_merger(flush_merger), + _framebuffer(framebuffer), _default_v_offset(default_v_offset) + { } }; @@ -673,7 +802,6 @@ struct Nitpicker::Main Sliced_heap sliced_heap = { env()->ram_session(), env()->rm_session() }; Root np_root = { session_list, global_keys, ep.rpc_ep(), - Area(mode.width(), mode.height()), user_state, sliced_heap, screen, framebuffer, MENUBAR_HEIGHT }; /* diff --git a/os/src/server/nitpicker/mouse_cursor.h b/os/src/server/nitpicker/mouse_cursor.h index 412cf20568..ea6647e424 100644 --- a/os/src/server/nitpicker/mouse_cursor.h +++ b/os/src/server/nitpicker/mouse_cursor.h @@ -37,7 +37,7 @@ class Mouse_cursor : public Chunky_texture, public Session, public View Mouse_cursor(PT const *pixels, Area size, View_stack const &view_stack) : Chunky_texture(pixels, 0, size), - Session(Genode::Session_label(""), *this, 0), + Session(Genode::Session_label(""), 0, false), View(*this, View::STAY_TOP, View::TRANSPARENT, View::NOT_BACKGROUND, Rect()), _view_stack(view_stack) diff --git a/os/src/server/nitpicker/session.h b/os/src/server/nitpicker/session.h index 3535d4b489..ab470f4d4f 100644 --- a/os/src/server/nitpicker/session.h +++ b/os/src/server/nitpicker/session.h @@ -37,7 +37,7 @@ class Session : public Session_list::Element Genode::Session_label const _label; Color _color; - Texture const &_texture; + Texture const *_texture; View *_background = 0; int _v_offset; unsigned char const *_input_mask; @@ -48,26 +48,14 @@ class Session : public Session_list::Element /** * Constructor * - * \param label session label - * \param texture texture containing the session's pixel - * representation - * \param v_offset vertical screen offset of session - * \param input_mask input mask buffer containing a byte value per - * texture pixel, which describes the policy of - * handling user input referring to the pixel. - * If set to zero, the input is passed through - * the view such that it can be handled by one of - * the subsequent views in the view stack. If set - * to one, the input is consumed by the view. If - * 'input_mask' is a null pointer, user input is - * unconditionally consumed by the view. + * \param label session label + * \param v_offset vertical screen offset of session + * \param stay_top true for views that stay always in front */ - Session(Genode::Session_label const &label, Texture const &texture, - int v_offset, unsigned char const *input_mask = 0, - bool stay_top = false) + Session(Genode::Session_label const &label, int v_offset, bool stay_top) : - _label(label), _texture(texture), _v_offset(v_offset), - _input_mask(input_mask), _stay_top(stay_top) + _label(label), _texture(0), _v_offset(v_offset), + _input_mask(0), _stay_top(stay_top) { } virtual ~Session() { } @@ -76,7 +64,23 @@ class Session : public Session_list::Element Genode::Session_label const &label() const { return _label; } - Texture const &texture() const { return _texture; } + Texture const *texture() const { return _texture; } + + void texture(Texture const *texture) { _texture = texture; } + + /** + * Set input mask buffer + * + * \param mask input mask buffer containing a byte value per texture + * pixel, which describes the policy of handling user + * input referring to the pixel. If set to zero, the input + * is passed through the view such that it can be handled + * by one of the subsequent views in the view stack. If + * set to one, the input is consumed by the view. If + * 'input_mask' is a null pointer, user input is + * unconditionally consumed by the view. + */ + void input_mask(unsigned char const *mask) { _input_mask = mask; } Color color() const { return _color; } @@ -89,7 +93,7 @@ class Session : public Session_list::Element /** * Return true if session uses an alpha channel */ - bool uses_alpha() const { return _texture.alpha(); } + bool uses_alpha() const { return _texture ? _texture->alpha() : 0; } /** * Return vertical offset of session @@ -101,14 +105,14 @@ class Session : public Session_list::Element */ unsigned char input_mask_at(Point p) const { - if (!_input_mask) return 0; + if (!_input_mask || !_texture) return 0; /* check boundaries */ - if (p.x() < 0 || p.x() >= _texture.w() - || p.y() < 0 || p.y() >= _texture.h()) + if (p.x() < 0 || p.x() >= _texture->w() + || p.y() < 0 || p.y() >= _texture->h()) return 0; - return _input_mask[p.y()*_texture.w() + p.x()]; + return _input_mask[p.y()*_texture->w() + p.x()]; } /** @@ -129,7 +133,6 @@ class Session : public Session_list::Element policy.attribute("color").value(&_color); } catch (...) { } } - }; #endif diff --git a/os/src/server/nitpicker/view.cc b/os/src/server/nitpicker/view.cc index a1abc4d3d0..8254a2e722 100644 --- a/os/src/server/nitpicker/view.cc +++ b/os/src/server/nitpicker/view.cc @@ -109,8 +109,9 @@ void View::draw(Canvas &canvas, Mode const &mode) const _session.color().g >> 1, _session.color().b >> 1); - canvas.draw_texture(_session.texture(), mix_color, _buffer_off + p1(), - op, allow_alpha); + if (_session.texture()) + canvas.draw_texture(*_session.texture(), mix_color, _buffer_off + p1(), + op, allow_alpha); if (mode.flat()) return; diff --git a/os/src/test/loader/main.cc b/os/src/test/loader/main.cc index f2ecfe7db0..1acfbf9304 100644 --- a/os/src/test/loader/main.cc +++ b/os/src/test/loader/main.cc @@ -33,12 +33,8 @@ int main(int argc, char **argv) sig_rec.wait_for_signal(); - Nitpicker::View_capability view_cap = loader.view(); - Loader::Session::View_geometry geometry = loader.view_geometry(); - - PDBG("w = %d, h = %d, buf_x = %d, buf_y = %d", - geometry.width, geometry.height, geometry.buf_x, geometry.buf_y); + Nitpicker::View_capability view_cap = loader.view(); Nitpicker::View_client view(view_cap); view.stack(Nitpicker::View_capability(), true, false); @@ -46,12 +42,12 @@ int main(int argc, char **argv) Timer::Connection timer; while(1) { - view.viewport(0, 0, geometry.width, geometry.height, - geometry.buf_x, geometry.buf_y, true); - timer.msleep(1000); - view.viewport(50, 50, geometry.width, geometry.height, - geometry.buf_x, geometry.buf_y, true); - timer.msleep(1000); + + for (unsigned i = 0; i < 10; i++) { + view.viewport(50*i, 50*i, geometry.width, geometry.height, + geometry.buf_x, geometry.buf_y, true); + timer.msleep(1000); + } } sleep_forever(); diff --git a/os/src/test/nitpicker/test.cc b/os/src/test/nitpicker/test.cc index da7df08779..048b688906 100644 --- a/os/src/test/nitpicker/test.cc +++ b/os/src/test/nitpicker/test.cc @@ -112,10 +112,12 @@ int main(int argc, char **argv) * Init sessions to the required external services */ enum { CONFIG_ALPHA = false }; - static Nitpicker::Connection nitpicker(256, 256, CONFIG_ALPHA); + static Nitpicker::Connection nitpicker; static Timer::Connection timer; - Framebuffer::Mode const mode = nitpicker.framebuffer()->mode(); + Framebuffer::Mode const mode(256, 256, Framebuffer::Mode::RGB565); + nitpicker.buffer(mode, false); + int const scr_w = mode.width(), scr_h = mode.height(); printf("screen is %dx%d\n", scr_w, scr_h); diff --git a/qt4/src/app/qt_avplay/framebuffer_session_component.cc b/qt4/src/app/qt_avplay/framebuffer_session_component.cc index f12b48ad5a..28ca4ab588 100644 --- a/qt4/src/app/qt_avplay/framebuffer_session_component.cc +++ b/qt4/src/app/qt_avplay/framebuffer_session_component.cc @@ -41,11 +41,14 @@ namespace Framebuffer { QNitpickerViewWidget &nitpicker_view_widget, int max_width, int max_height) - : _nitpicker(Nitpicker::Connection( - _limited_size(session_arg(args, "fb_width"), max_width), - _limited_size(session_arg(args, "fb_height"), max_height))), + : _framebuffer(_nitpicker.framebuffer_session()) { + Framebuffer::Mode const + mode(_limited_size(session_arg(args, "fb_width"), max_width), + _limited_size(session_arg(args, "fb_height"), max_height), + _nitpicker.mode().format()); + _nitpicker.buffer(mode, false); Nitpicker::View_capability nitpicker_view_cap = _nitpicker.create_view(); Mode _mode = _framebuffer.mode(); nitpicker_view_widget.setNitpickerView(nitpicker_view_cap, diff --git a/qt4/src/lib/qt4/src/gui/embedded/qscreennitpicker_qws.cpp b/qt4/src/lib/qt4/src/gui/embedded/qscreennitpicker_qws.cpp index 4394850484..f66333aaee 100644 --- a/qt4/src/lib/qt4/src/gui/embedded/qscreennitpicker_qws.cpp +++ b/qt4/src/lib/qt4/src/gui/embedded/qscreennitpicker_qws.cpp @@ -173,9 +173,11 @@ bool QNitpickerScreen::connect(const QString &displaySpec) nitpicker = new Nitpicker::Connection(); framebuffer = new Framebuffer::Session_client(nitpicker->framebuffer_session()); - Framebuffer::Mode const scr_mode = framebuffer->mode(); + Framebuffer::Mode const scr_mode = nitpicker->mode(); int const scr_w = scr_mode.width(), scr_h = scr_mode.height(); + nitpicker->buffer(scr_mode, false); + qDebug() << "screen is " << scr_w << "x" << scr_h; if (!scr_w || !scr_h) { qDebug("got invalid screen - spinning");