framebuffer_session: alpha as Mode attribute

Propagate the want of an alpha channel as attribute of Framebuffer::Mode
instead of passing this property as a separate bool argument.

This clears the way for adding useful accessors for pixel/alpha/input
surfaces to the Mode type as a subsequent step.

Issue #5351
This commit is contained in:
Norman Feske
2024-09-25 11:34:39 +02:00
committed by Christian Helmuth
parent 336d481726
commit e738162bde
38 changed files with 149 additions and 154 deletions

View File

@ -45,9 +45,7 @@ class Scout::Graphics_backend_impl : public Graphics_backend
Genode::Dataspace_capability _init_fb_ds(Area max_size) Genode::Dataspace_capability _init_fb_ds(Area max_size)
{ {
Framebuffer::Mode const mode { .area = { max_size.w, max_size.h*2 }}; _gui.buffer({ .area = { max_size.w, max_size.h*2 }, .alpha = false });
_gui.buffer(mode, false);
return _gui.framebuffer.dataspace(); return _gui.framebuffer.dataspace();
} }

View File

@ -239,10 +239,10 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Session>
public: public:
Session_component(Genode::Env &env, Window_content &window_content) Session_component(Env &env, Window_content &window_content)
: _timer(env), _window_content(window_content) { } : _timer(env), _window_content(window_content) { }
Genode::Dataspace_capability dataspace() override Dataspace_capability dataspace() override
{ {
_window_content.realloc_framebuffer(); _window_content.realloc_framebuffer();
return _window_content.fb_ds_cap(); return _window_content.fb_ds_cap();
@ -250,13 +250,15 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Session>
Mode mode() const override Mode mode() const override
{ {
return Mode { .area = _window_content.mode_size() }; return { .area = _window_content.mode_size(), .alpha = false };
} }
void mode_sigh(Genode::Signal_context_capability sigh) override { void mode_sigh(Signal_context_capability sigh) override
_window_content.mode_sigh(sigh); } {
_window_content.mode_sigh(sigh);
}
void sync_sigh(Genode::Signal_context_capability sigh) override void sync_sigh(Signal_context_capability sigh) override
{ {
_timer.sigh(sigh); _timer.sigh(sigh);
_timer.trigger_periodic(10*1000); _timer.trigger_periodic(10*1000);

View File

@ -366,7 +366,7 @@ struct Nitlog::Main
void _init_gui_buffer() void _init_gui_buffer()
{ {
_gui.buffer(Framebuffer::Mode { .area = { _win_w, _win_h } }, false); _gui.buffer({ .area = { _win_w, _win_h }, .alpha = false });
} }
bool const _gui_buffer_initialized = (_init_gui_buffer(), true); bool const _gui_buffer_initialized = (_init_gui_buffer(), true);

View File

@ -45,8 +45,6 @@ struct Gui_buffer : Genode::Noncopyable
Framebuffer::Mode const mode; Framebuffer::Mode const mode;
bool const use_alpha;
Pixel_rgb888 const reset_color; Pixel_rgb888 const reset_color;
/** /**
@ -58,7 +56,8 @@ struct Gui_buffer : Genode::Noncopyable
* Setup virtual framebuffer, the upper part containing the front * Setup virtual framebuffer, the upper part containing the front
* buffer, the lower part containing the back buffer. * buffer, the lower part containing the back buffer.
*/ */
gui.buffer({ .area = { mode.area.w, mode.area.h*2 } }, use_alpha); gui.buffer({ .area = { mode.area.w, mode.area.h*2 },
.alpha = mode.alpha });
return gui.framebuffer.dataspace(); return gui.framebuffer.dataspace();
} }
@ -66,8 +65,8 @@ struct Gui_buffer : Genode::Noncopyable
Genode::Attached_dataspace _fb_ds { rm, _ds_cap(gui) }; Genode::Attached_dataspace _fb_ds { rm, _ds_cap(gui) };
size_t _pixel_num_bytes() const { return size().count()*sizeof(Pixel_rgb888); } size_t _pixel_num_bytes() const { return size().count()*sizeof(Pixel_rgb888); }
size_t _alpha_num_bytes() const { return use_alpha ? size().count() : 0; } size_t _alpha_num_bytes() const { return mode.alpha ? size().count() : 0; }
size_t _input_num_bytes() const { return use_alpha ? size().count() : 0; } size_t _input_num_bytes() const { return mode.alpha ? size().count() : 0; }
void _with_pixel_ptr(auto const &fn) void _with_pixel_ptr(auto const &fn)
{ {
@ -78,7 +77,7 @@ struct Gui_buffer : Genode::Noncopyable
void _with_alpha_ptr(auto const &fn) void _with_alpha_ptr(auto const &fn)
{ {
if (!use_alpha) if (!mode.alpha)
return; return;
/* skip pixel front buffer, pixel back buffer, and alpha front buffer */ /* skip pixel front buffer, pixel back buffer, and alpha front buffer */
@ -89,7 +88,7 @@ struct Gui_buffer : Genode::Noncopyable
void _with_input_ptr(auto const &fn) void _with_input_ptr(auto const &fn)
{ {
if (!use_alpha) if (!mode.alpha)
return; return;
/* skip pixel buffers, alpha buffers, and input front buffer */ /* skip pixel buffers, alpha buffers, and input front buffer */
@ -120,8 +119,8 @@ struct Gui_buffer : Genode::Noncopyable
: :
ram(ram), rm(rm), gui(gui), ram(ram), rm(rm), gui(gui),
mode({ .area = { Genode::max(1U, size.w), mode({ .area = { Genode::max(1U, size.w),
Genode::max(1U, size.h) } }), Genode::max(1U, size.h) },
use_alpha(alpha == Alpha::ALPHA), .alpha = (alpha == Alpha::ALPHA) }),
reset_color(reset_color.r, reset_color.g, reset_color.b, reset_color.a) reset_color(reset_color.r, reset_color.g, reset_color.b, reset_color.a)
{ {
reset_surface(); reset_surface();

View File

@ -86,10 +86,9 @@ class Nano3d::Scene
* visible view because it contains the visible buffer, the * visible view because it contains the visible buffer, the
* front buffer, and the back buffer. * front buffer, and the back buffer.
*/ */
bool const use_alpha = true; gui.buffer({ .area = { .w = size.w,
unsigned const height = size.h*NUM_BUFFERS; .h = size.h*NUM_BUFFERS },
gui.buffer(Framebuffer::Mode { .area = { size.w, height } }, .alpha = true });
use_alpha);
return gui.framebuffer; return gui.framebuffer;
} }

View File

@ -59,7 +59,7 @@ struct Backdrop::Main
Dataspace_capability _ds_cap(Gui::Connection &gui) Dataspace_capability _ds_cap(Gui::Connection &gui)
{ {
/* setup virtual framebuffer mode */ /* setup virtual framebuffer mode */
gui.buffer(mode, false); gui.buffer(mode);
return gui.framebuffer.dataspace(); return gui.framebuffer.dataspace();
} }
@ -314,9 +314,11 @@ void Backdrop::Main::_handle_config()
_config.update(); _config.update();
Framebuffer::Mode const phys_mode = _gui.mode(); Framebuffer::Mode const phys_mode = _gui.mode();
Framebuffer::Mode const Framebuffer::Mode const mode {
mode { .area = { _config.xml().attribute_value("width", phys_mode.area.w), .area = { _config.xml().attribute_value("width", phys_mode.area.w),
_config.xml().attribute_value("height", phys_mode.area.h) } }; _config.xml().attribute_value("height", phys_mode.area.h) },
.alpha = false
};
_buffer.construct(_env, _gui, mode); _buffer.construct(_env, _gui, mode);

View File

@ -66,9 +66,10 @@ struct Decorator::Main : Window_factory_base
* whereas the lower part contains the back buffer targeted by * whereas the lower part contains the back buffer targeted by
* the Decorator::Canvas. * the Decorator::Canvas.
*/ */
Framebuffer::Mode _mode_doubled() const static Framebuffer::Mode _doubled(Framebuffer::Mode const mode)
{ {
return { { .w = mode.area.w, .h = mode.area.h*2 } }; return { .area = { .w = mode.area.w, .h = mode.area.h*2 },
.alpha = mode.alpha };
} }
Pixel_rgb888 *_canvas_pixels_ptr() Pixel_rgb888 *_canvas_pixels_ptr()
@ -80,7 +81,7 @@ struct Decorator::Main : Window_factory_base
: :
mode(gui.mode()), mode(gui.mode()),
fb_ds(env.rm(), fb_ds(env.rm(),
(gui.buffer(_mode_doubled(), false), gui.framebuffer.dataspace())), (gui.buffer(_doubled(mode)), gui.framebuffer.dataspace())),
canvas(_canvas_pixels_ptr(), mode.area, env.ram(), env.rm()) canvas(_canvas_pixels_ptr(), mode.area, env.ram(), env.rm())
{ } { }
}; };

View File

@ -151,8 +151,8 @@ struct Gui::Session_component : Rpc_object<Gui::Session>
void mode_sigh(Signal_context_capability sigh) override { void mode_sigh(Signal_context_capability sigh) override {
_gui_session.mode_sigh(sigh); } _gui_session.mode_sigh(sigh); }
Buffer_result buffer(Framebuffer::Mode mode, bool use_alpha) override { Buffer_result buffer(Framebuffer::Mode mode) override {
return _gui_session.buffer(mode, use_alpha); } return _gui_session.buffer(mode); }
void focus(Capability<Gui::Session> session) override { void focus(Capability<Gui::Session> session) override {
_gui_session.focus(session); } _gui_session.focus(session); }

View File

@ -300,17 +300,15 @@ class Decorator::Window : public Window_base, public Animator::Item
void _reallocate_gui_buffers() void _reallocate_gui_buffers()
{ {
bool const use_alpha = true;
Area const size_top_bottom = _visible_top_bottom_area(geometry().area); Area const size_top_bottom = _visible_top_bottom_area(geometry().area);
if (size_top_bottom.w > _size_top_bottom.w if (size_top_bottom.w > _size_top_bottom.w
|| size_top_bottom.h > _size_top_bottom.h || size_top_bottom.h > _size_top_bottom.h
|| !_buffer_top_bottom.constructed()) { || !_buffer_top_bottom.constructed()) {
_gui_top_bottom.buffer(Framebuffer::Mode { .area = { size_top_bottom.w, _gui_top_bottom.buffer({ .area = { size_top_bottom.w,
size_top_bottom.h } }, size_top_bottom.h },
use_alpha); .alpha = true });
_buffer_top_bottom.construct(_gui_top_bottom, size_top_bottom, _buffer_top_bottom.construct(_gui_top_bottom, size_top_bottom,
_env.ram(), _env.rm()); _env.ram(), _env.rm());
@ -324,9 +322,9 @@ class Decorator::Window : public Window_base, public Animator::Item
|| size_left_right.h > _size_left_right.h || size_left_right.h > _size_left_right.h
|| !_buffer_left_right.constructed()) { || !_buffer_left_right.constructed()) {
_gui_left_right.buffer(Framebuffer::Mode { .area = { size_left_right.w, _gui_left_right.buffer({ .area = { size_left_right.w,
size_left_right.h } }, size_left_right.h },
use_alpha); .alpha = true });
_buffer_left_right.construct(_gui_left_right, size_left_right, _buffer_left_right.construct(_gui_left_right, size_left_right,
_env.ram(), _env.rm()); _env.ram(), _env.rm());

View File

@ -156,8 +156,8 @@ struct Sandboxed_runtime::Gui_session : Session_object<Gui::Session>
void mode_sigh(Signal_context_capability sigh) override { void mode_sigh(Signal_context_capability sigh) override {
_gui_session.mode_sigh(sigh); } _gui_session.mode_sigh(sigh); }
Buffer_result buffer(Framebuffer::Mode mode, bool use_alpha) override { Buffer_result buffer(Framebuffer::Mode mode) override {
return _gui_session.buffer(mode, use_alpha); } return _gui_session.buffer(mode); }
void focus(Capability<Gui::Session> session) override { void focus(Capability<Gui::Session> session) override {
_gui_session.focus(session); } _gui_session.focus(session); }

View File

@ -43,6 +43,7 @@ namespace Gui_fader {
using Rect = Genode::Surface_base::Rect; using Rect = Genode::Surface_base::Rect;
using Genode::size_t; using Genode::size_t;
using Genode::uint8_t;
using Genode::Xml_node; using Genode::Xml_node;
using Genode::Dataspace_capability; using Genode::Dataspace_capability;
using Genode::Attached_ram_dataspace; using Genode::Attached_ram_dataspace;
@ -65,7 +66,6 @@ class Gui_fader::Src_buffer
using Pixel = Pixel_rgb888; using Pixel = Pixel_rgb888;
bool const _use_alpha;
Attached_ram_dataspace _ds; Attached_ram_dataspace _ds;
Texture<Pixel> _texture; Texture<Pixel> _texture;
bool _warned_once = false; bool _warned_once = false;
@ -84,27 +84,24 @@ class Gui_fader::Src_buffer
public: public:
/** Src_buffer(Genode::Env &env, Framebuffer::Mode mode)
* Constructor
*/
Src_buffer(Genode::Env &env, Area size, bool use_alpha)
: :
_use_alpha(use_alpha), _ds(env.ram(), env.rm(), _needed_bytes(mode.area)),
_ds(env.ram(), env.rm(), _needed_bytes(size)),
_texture(_ds.local_addr<Pixel>(), _texture(_ds.local_addr<Pixel>(),
_ds.local_addr<unsigned char>() + size.count()*sizeof(Pixel), mode.alpha ? _ds.local_addr<uint8_t>() + mode.area.count()*sizeof(Pixel)
size) : nullptr,
mode.area)
{ } { }
Dataspace_capability dataspace() { return _ds.cap(); } Dataspace_capability dataspace() { return _ds.cap(); }
Texture<Pixel> const &texture() const { return _texture; } Texture<Pixel> const &texture() const { return _texture; }
bool use_alpha() const { return _use_alpha; } bool use_alpha() const { return _texture.alpha(); }
void blit(Rect from, Point to) void blit(Rect from, Point to)
{ {
if (_use_alpha && !_warned_once) { if (_texture.alpha() && !_warned_once) {
Genode::warning("Framebuffer::Session::blit does not support alpha blending"); Genode::warning("Framebuffer::Session::blit does not support alpha blending");
_warned_once = true; _warned_once = true;
} }
@ -267,7 +264,8 @@ class Gui_fader::Framebuffer_session_component
Blit_result blit(Framebuffer::Blit_batch const &batch) override Blit_result blit(Framebuffer::Blit_batch const &batch) override
{ {
Framebuffer::Mode const mode { .area = _src_buffer.texture().size() }; Framebuffer::Mode const mode { .area = _src_buffer.texture().size(),
.alpha = false };
for (Framebuffer::Transfer const &transfer : batch.transfer) { for (Framebuffer::Transfer const &transfer : batch.transfer) {
if (transfer.valid(mode)) { if (transfer.valid(mode)) {
_src_buffer.blit(transfer.from, transfer.to); _src_buffer.blit(transfer.from, transfer.to);
@ -306,7 +304,8 @@ class Gui_fader::Gui_session_component
Genode::Env &_env; Genode::Env &_env;
Reconstructible<Src_buffer> _src_buffer { _env, Area(1, 1), false }; Reconstructible<Src_buffer> _src_buffer {
_env, Framebuffer::Mode { .area = { 1, 1 }, .alpha = false } };
Gui::Connection _gui { _env }; Gui::Connection _gui { _env };
@ -464,15 +463,13 @@ class Gui_fader::Gui_session_component
_gui.mode_sigh(sigh); _gui.mode_sigh(sigh);
} }
Buffer_result buffer(Framebuffer::Mode mode, bool use_alpha) override Buffer_result buffer(Framebuffer::Mode mode) override
{ {
Area const size = mode.area; _src_buffer.construct(_env, mode);
_src_buffer.construct(_env, size, use_alpha); _gui.buffer({ .area = mode.area, .alpha = true });
_gui.buffer(mode, true); _fb_session.dst_buffer(_gui.framebuffer.dataspace(), mode.area);
_fb_session.dst_buffer(_gui.framebuffer.dataspace(), size);
return Buffer_result::OK; return Buffer_result::OK;
} }

View File

@ -217,7 +217,7 @@ struct Terminal::Main : Character_consumer
_gui.input.sigh(_input_handler); _gui.input.sigh(_input_handler);
_gui.mode_sigh(_mode_change_handler); _gui.mode_sigh(_mode_change_handler);
_fb_mode = _gui.mode(); _fb_mode = { .area = _gui.mode().area, .alpha = false };
/* apply initial size from config, if provided */ /* apply initial size from config, if provided */
_config.xml().with_optional_sub_node("initial", [&] (Xml_node const &initial) { _config.xml().with_optional_sub_node("initial", [&] (Xml_node const &initial) {
@ -259,7 +259,7 @@ void Terminal::Main::_handle_config()
/* /*
* Adapt terminal to font or framebuffer mode changes * Adapt terminal to font or framebuffer mode changes
*/ */
_gui.buffer(_fb_mode, false); _gui.buffer(_fb_mode);
if (_fb_mode.area.count() > 0) if (_fb_mode.area.count() > 0)
_fb_ds.construct(_env.rm(), _gui.framebuffer.dataspace()); _fb_ds.construct(_env.rm(), _gui.framebuffer.dataspace());

View File

@ -331,9 +331,9 @@ struct Wm::Decorator_gui_session : Session_object<Gui::Session>,
_real_gui.session.mode_sigh(sigh); _real_gui.session.mode_sigh(sigh);
} }
Buffer_result buffer(Framebuffer::Mode mode, bool use_alpha) override Buffer_result buffer(Framebuffer::Mode mode) override
{ {
return _real_gui.session.buffer(mode, use_alpha); return _real_gui.session.buffer(mode);
} }
void focus(Capability<Gui::Session>) override { } void focus(Capability<Gui::Session>) override { }

View File

@ -114,9 +114,9 @@ class Wm::Direct_gui_session : public Session_object<Gui::Session>
_session.mode_sigh(sigh); _session.mode_sigh(sigh);
} }
Buffer_result buffer(Framebuffer::Mode mode, bool use_alpha) override Buffer_result buffer(Framebuffer::Mode mode) override
{ {
return _session.buffer(mode, use_alpha); return _session.buffer(mode);
} }
void focus(Capability<Gui::Session> session) override void focus(Capability<Gui::Session> session) override

View File

@ -1170,7 +1170,8 @@ class Wm::Gui::Session_component : public Session_object<Gui::Session>,
* mode * mode
*/ */
if (_resize_requested) if (_resize_requested)
return Framebuffer::Mode { .area = _requested_size }; return Framebuffer::Mode { .area = _requested_size,
.alpha = real_mode.alpha };
/* /*
* If the first top-level view has a defined size, use it * If the first top-level view has a defined size, use it
@ -1178,7 +1179,8 @@ class Wm::Gui::Session_component : public Session_object<Gui::Session>,
*/ */
if (Top_level_view const *v = _top_level_views.first()) if (Top_level_view const *v = _top_level_views.first())
if (v->size().valid()) if (v->size().valid())
return Framebuffer::Mode { .area = v->size() }; return Framebuffer::Mode { .area = v->size(),
.alpha = real_mode.alpha};
/* /*
* If top-level view has yet been defined, return the real mode. * If top-level view has yet been defined, return the real mode.
@ -1200,7 +1202,7 @@ class Wm::Gui::Session_component : public Session_object<Gui::Session>,
v->resizeable(resizeable); v->resizeable(resizeable);
} }
Buffer_result buffer(Framebuffer::Mode mode, bool has_alpha) override Buffer_result buffer(Framebuffer::Mode mode) override
{ {
/* /*
* We must not perform the 'buffer' operation on the connection * We must not perform the 'buffer' operation on the connection
@ -1211,9 +1213,9 @@ class Wm::Gui::Session_component : public Session_object<Gui::Session>,
* wrapped GUI session. Otherwise, we would perform session * wrapped GUI session. Otherwise, we would perform session
* upgrades initiated by the wm client's buffer operation twice. * upgrades initiated by the wm client's buffer operation twice.
*/ */
_has_alpha = has_alpha; _has_alpha = mode.alpha;
Buffer_result const result = _real_gui.session.buffer(mode, has_alpha); Buffer_result const result = _real_gui.session.buffer(mode);
_window_registry.flush(); _window_registry.flush();
return result; return result;

View File

@ -107,7 +107,7 @@ struct Wm::Layouter_gui_session : Session_object<Gui::Session>
_mode_sigh_gui.mode_sigh(sigh); _mode_sigh_gui.mode_sigh(sigh);
} }
Buffer_result buffer(Framebuffer::Mode, bool) override { return Buffer_result::OK; } Buffer_result buffer(Framebuffer::Mode) override { return Buffer_result::OK; }
void focus(Capability<Gui::Session>) override { } void focus(Capability<Gui::Session>) override { }
}; };

View File

@ -87,8 +87,6 @@ class Pdf_view
private: private:
enum { NO_ALPHA = false };
Genode::Env &_env; Genode::Env &_env;
Gui::Connection _gui { _env }; Gui::Connection _gui { _env };
@ -118,8 +116,8 @@ class Pdf_view
unsigned max_y = Genode::max(_nit_mode.area.h, _fb_mode.area.h); unsigned max_y = Genode::max(_nit_mode.area.h, _fb_mode.area.h);
if (max_x > _fb_mode.area.w || max_y > _fb_mode.area.h) { if (max_x > _fb_mode.area.w || max_y > _fb_mode.area.h) {
_fb_mode = Mode { .area = { max_x, max_y } }; _fb_mode = Mode { .area = { max_x, max_y }, .alpha = false };
_gui.buffer(_fb_mode, NO_ALPHA); _gui.buffer(_fb_mode);
if (_fb_ds.constructed()) if (_fb_ds.constructed())
_fb_ds.destruct(); _fb_ds.destruct();
_fb_ds.construct(_env.rm(), _gui.framebuffer.dataspace()); _fb_ds.construct(_env.rm(), _gui.framebuffer.dataspace());

View File

@ -61,7 +61,7 @@ class Viewer
_env { env }, _env { env },
_mode { mode } _mode { mode }
{ {
_gui.buffer(mode, false); _gui.buffer(mode);
_fb_ds.construct(_env.rm(), _gui.framebuffer.dataspace()); _fb_ds.construct(_env.rm(), _gui.framebuffer.dataspace());
_framebuffer = _fb_ds->local_addr<uint8_t>(); _framebuffer = _fb_ds->local_addr<uint8_t>();
@ -275,10 +275,10 @@ class Main
if (_webcam.constructed()) if (_webcam.constructed())
_webcam.destruct(); _webcam.destruct();
Framebuffer::Mode mode { .area = { width, height }, .alpha = false };
if (enabled) { if (enabled) {
try { try {
_webcam.construct(_env, Framebuffer::Mode { _webcam.construct(_env, mode, frame_format, fps);
.area = { width, height } }, frame_format, fps);
} catch (...) { } } catch (...) { }
} }
} }

View File

@ -57,13 +57,13 @@ struct Window : Genode_egl_window
Window(Genode::Env &env, int w, int h) Window(Genode::Env &env, int w, int h)
: :
env(env), mode { .area = Gui::Area(w, h) } env(env), mode { .area = Gui::Area(w, h), .alpha = false }
{ {
width = w; width = w;
height = h; height = h;
type = WINDOW; type = WINDOW;
gui.buffer(mode, false); gui.buffer(mode);
mode_change(); mode_change();
} }

View File

@ -34,6 +34,7 @@ namespace Framebuffer {
struct Mode struct Mode
{ {
Area area; Area area;
bool alpha;
size_t bytes_per_pixel() const { return 4; } size_t bytes_per_pixel() const { return 4; }

View File

@ -59,8 +59,8 @@ struct Gui::Session_client : Rpc_client<Session>
void mode_sigh(Signal_context_capability sigh) override { void mode_sigh(Signal_context_capability sigh) override {
call<Rpc_mode_sigh>(sigh); } call<Rpc_mode_sigh>(sigh); }
[[nodiscard]] Buffer_result buffer(Framebuffer::Mode mode, bool alpha) override { [[nodiscard]] Buffer_result buffer(Framebuffer::Mode mode) override {
return call<Rpc_buffer>(mode, alpha); } return call<Rpc_buffer>(mode); }
void focus(Gui::Session_capability session) override { void focus(Gui::Session_capability session) override {
call<Rpc_focus>(session); } call<Rpc_focus>(session); }

View File

@ -154,9 +154,9 @@ class Gui::Connection : private Genode::Connection<Session>
} }
} }
void buffer(Framebuffer::Mode mode, bool use_alpha) void buffer(Framebuffer::Mode mode)
{ {
size_t const needed = Session_client::ram_quota(mode, use_alpha); size_t const needed = Session_client::ram_quota(mode);
size_t const upgrade = needed > _ram_quota.value size_t const upgrade = needed > _ram_quota.value
? needed - _ram_quota.value : 0u; ? needed - _ram_quota.value : 0u;
if (upgrade > 0) { if (upgrade > 0) {
@ -166,7 +166,7 @@ class Gui::Connection : private Genode::Connection<Session>
for (bool retry = false; ; ) { for (bool retry = false; ; ) {
using Result = Session_client::Buffer_result; using Result = Session_client::Buffer_result;
auto const result = _client.buffer(mode, use_alpha); auto const result = _client.buffer(mode);
if (result == Result::OUT_OF_RAM) { upgrade_ram(8*1024); retry = true; } if (result == Result::OUT_OF_RAM) { upgrade_ram(8*1024); retry = true; }
if (result == Result::OUT_OF_CAPS) { upgrade_caps(2); retry = true; } if (result == Result::OUT_OF_CAPS) { upgrade_caps(2); retry = true; }
if (!retry) if (!retry)

View File

@ -248,7 +248,7 @@ struct Gui::Session : Genode::Session
/** /**
* Define dimensions of virtual framebuffer * Define dimensions of virtual framebuffer
*/ */
virtual Buffer_result buffer(Framebuffer::Mode mode, bool use_alpha) = 0; virtual Buffer_result buffer(Framebuffer::Mode mode) = 0;
/** /**
* Set focused session * Set focused session
@ -268,13 +268,13 @@ struct Gui::Session : Genode::Session
/** /**
* Return number of bytes needed for virtual framebuffer of specified size * Return number of bytes needed for virtual framebuffer of specified size
*/ */
static size_t ram_quota(Framebuffer::Mode mode, bool use_alpha) static size_t ram_quota(Framebuffer::Mode mode)
{ {
/* /*
* If alpha blending is used, each pixel requires an additional byte * If alpha blending is used, each pixel requires an additional byte
* for the alpha value and a byte holding the input mask. * for the alpha value and a byte holding the input mask.
*/ */
return (mode.bytes_per_pixel() + 2*use_alpha)*mode.area.count(); return (mode.bytes_per_pixel() + 2*mode.alpha)*mode.area.count();
} }
@ -296,7 +296,7 @@ struct Gui::Session : Genode::Session
GENODE_RPC(Rpc_mode, Framebuffer::Mode, mode); GENODE_RPC(Rpc_mode, Framebuffer::Mode, mode);
GENODE_RPC(Rpc_mode_sigh, void, mode_sigh, Signal_context_capability); GENODE_RPC(Rpc_mode_sigh, void, mode_sigh, Signal_context_capability);
GENODE_RPC(Rpc_focus, void, focus, Capability<Session>); GENODE_RPC(Rpc_focus, void, focus, Capability<Session>);
GENODE_RPC(Rpc_buffer, Buffer_result, buffer, Framebuffer::Mode, bool); GENODE_RPC(Rpc_buffer, Buffer_result, buffer, Framebuffer::Mode);
GENODE_RPC_INTERFACE(Rpc_framebuffer, Rpc_input, GENODE_RPC_INTERFACE(Rpc_framebuffer, Rpc_input,
Rpc_view, Rpc_child_view, Rpc_destroy_view, Rpc_associate, Rpc_view, Rpc_child_view, Rpc_destroy_view, Rpc_associate,

View File

@ -133,9 +133,7 @@ void Pointer::Main::_resize_gui_buffer_if_needed(Gui::Area pointer_size)
if (pointer_size == _current_pointer_size) if (pointer_size == _current_pointer_size)
return; return;
Framebuffer::Mode const mode { .area = pointer_size }; _gui.buffer({ .area = pointer_size, .alpha = true });
_gui.buffer(mode, true /* use alpha */);
_pointer_ds = _gui.framebuffer.dataspace(); _pointer_ds = _gui.framebuffer.dataspace();
@ -333,9 +331,9 @@ Pointer::Main::Main(Genode::Env &env) : _env(env)
* pointer size to let the user know right from the start if the * pointer size to let the user know right from the start if the
* RAM quota is too low. * RAM quota is too low.
*/ */
Framebuffer::Mode const mode { .area = { Pointer::MAX_WIDTH, Pointer::MAX_HEIGHT } };
_gui.buffer(mode, true /* use alpha */); _gui.buffer({ .area = { Pointer::MAX_WIDTH, Pointer::MAX_HEIGHT },
.alpha = true });
if (_shapes_enabled) { if (_shapes_enabled) {
try { try {

View File

@ -51,11 +51,12 @@ struct Status_bar::Buffer
* The status bar is as wide as nitpicker's screen and has a fixed * The status bar is as wide as nitpicker's screen and has a fixed
* height. * height.
*/ */
Framebuffer::Mode const _mode { .area = { _nit_mode.area.w, HEIGHT } }; Framebuffer::Mode const _mode { .area = { _nit_mode.area.w, HEIGHT },
.alpha = false };
Dataspace_capability _init_buffer() Dataspace_capability _init_buffer()
{ {
_gui.buffer(_mode, false); _gui.buffer(_mode);
return _gui.framebuffer.dataspace(); return _gui.framebuffer.dataspace();
} }

View File

@ -124,7 +124,7 @@ struct Framebuffer::Session_component : Genode::Rpc_object<Framebuffer::Session>
{ {
/* calculation in bytes */ /* calculation in bytes */
size_t const used = _buffer_num_bytes, size_t const used = _buffer_num_bytes,
needed = Gui::Session::ram_quota(mode, false), needed = Gui::Session::ram_quota(mode),
usable = _pd.avail_ram().value, usable = _pd.avail_ram().value,
preserved = 64*1024; preserved = 64*1024;
@ -157,7 +157,7 @@ struct Framebuffer::Session_component : Genode::Rpc_object<Framebuffer::Session>
if (Gui::Area(_next_mode.area.w, _next_mode.area.h) == size) if (Gui::Area(_next_mode.area.w, _next_mode.area.h) == size)
return; return;
Framebuffer::Mode const mode { .area = size }; Framebuffer::Mode const mode { .area = size, .alpha = false };
if (!_ram_suffices_for_mode(mode)) { if (!_ram_suffices_for_mode(mode)) {
warning("insufficient RAM for mode ", mode); warning("insufficient RAM for mode ", mode);
@ -182,10 +182,10 @@ struct Framebuffer::Session_component : Genode::Rpc_object<Framebuffer::Session>
Dataspace_capability dataspace() override Dataspace_capability dataspace() override
{ {
_gui.buffer(_active_mode, false); _gui.buffer(_active_mode);
_buffer_num_bytes = _buffer_num_bytes =
max(_buffer_num_bytes, Gui::Session::ram_quota(_active_mode, false)); max(_buffer_num_bytes, Gui::Session::ram_quota(_active_mode));
/* /*
* We defer the update of the view until the client calls refresh the * We defer the update of the view until the client calls refresh the
@ -294,8 +294,11 @@ struct Gui_fb::Main : View_updater
Framebuffer::Mode _initial_mode() Framebuffer::Mode _initial_mode()
{ {
return Framebuffer::Mode { .area = { _initial_size.width (_gui.mode()), return {
_initial_size.height(_gui.mode()) } }; .area = { _initial_size.width (_gui.mode()),
_initial_size.height(_gui.mode()) },
.alpha = false
};
} }
/* /*

View File

@ -61,11 +61,11 @@ namespace Nitpicker { struct Buffer_provider; }
/** /**
* Interface for triggering the re-allocation of a virtual framebuffer * Interface for triggering the re-allocation of a virtual framebuffer
* *
* Used by 'Framebuffer::Session_component', * implemented by 'Gui_session' * Used by 'Framebuffer::Session_component', implemented by 'Gui_session'
*/ */
struct Nitpicker::Buffer_provider : Interface struct Nitpicker::Buffer_provider : Interface
{ {
virtual Dataspace_capability realloc_buffer(Framebuffer::Mode, bool use_alpha) = 0; virtual Dataspace_capability realloc_buffer(Framebuffer::Mode) = 0;
virtual void blit(Rect from, Point to) = 0; virtual void blit(Rect from, Point to) = 0;

View File

@ -33,12 +33,13 @@ class Nitpicker::Chunky_texture : public Buffer, public Texture<PT>
/** /**
* Return base address of alpha channel or 0 if no alpha channel exists * Return base address of alpha channel or 0 if no alpha channel exists
*/ */
unsigned char *_alpha_base(Area size, bool use_alpha) unsigned char *_alpha_base(Framebuffer::Mode mode)
{ {
if (!use_alpha) return 0; if (!mode.alpha) return nullptr;
/* alpha values come right after the pixel values */ /* alpha values come right after the pixel values */
return (unsigned char *)local_addr() + calc_num_bytes(size, false); return (unsigned char *)local_addr()
+ calc_num_bytes({ .area = mode.area, .alpha = false });
} }
Area _area() const { return Texture<PT>::size(); } Area _area() const { return Texture<PT>::size(); }
@ -104,13 +105,13 @@ class Nitpicker::Chunky_texture : public Buffer, public Texture<PT>
/** /**
* Constructor * Constructor
*/ */
Chunky_texture(Ram_allocator &ram, Region_map &rm, Area size, bool use_alpha) Chunky_texture(Ram_allocator &ram, Region_map &rm, Framebuffer::Mode mode)
: :
Buffer(ram, rm, size, calc_num_bytes(size, use_alpha)), Buffer(ram, rm, mode.area, calc_num_bytes(mode)),
Texture<PT>((PT *)local_addr(), Texture<PT>((PT *)local_addr(), _alpha_base(mode), mode.area)
_alpha_base(size, use_alpha), size) { } { }
static size_t calc_num_bytes(Area size, bool use_alpha) static size_t calc_num_bytes(Framebuffer::Mode mode)
{ {
/* /*
* If using an alpha channel, the alpha buffer follows the * If using an alpha channel, the alpha buffer follows the
@ -118,19 +119,17 @@ class Nitpicker::Chunky_texture : public Buffer, public Texture<PT>
* mask buffer. Hence, we have to account one byte per * mask buffer. Hence, we have to account one byte per
* alpha value and one byte for the input mask value. * alpha value and one byte for the input mask value.
*/ */
size_t bytes_per_pixel = sizeof(PT) + (use_alpha ? 2 : 0); size_t bytes_per_pixel = sizeof(PT) + (mode.alpha ? 2 : 0);
return bytes_per_pixel*size.count(); return bytes_per_pixel*mode.area.count();
} }
unsigned char const *input_mask_buffer() const uint8_t const *input_mask_buffer() const
{ {
if (!Texture<PT>::alpha()) return 0; if (!Texture<PT>::alpha()) return 0;
Area const size = Texture<PT>::size();
/* input-mask values come right after the alpha values */ /* input-mask values come right after the alpha values */
return (unsigned char const *)local_addr() + calc_num_bytes(size, false) Framebuffer::Mode const mode { .area = _area(), .alpha = false };
+ size.count(); return (uint8_t const *)local_addr() + calc_num_bytes(mode) + _area().count();
} }
void blit(Rect from, Point to) void blit(Rect from, Point to)

View File

@ -45,7 +45,6 @@ class Framebuffer::Session_component : public Rpc_object<Session>
Signal_context_capability _mode_sigh { }; Signal_context_capability _mode_sigh { };
Signal_context_capability _sync_sigh { }; Signal_context_capability _sync_sigh { };
Framebuffer::Mode _mode { }; Framebuffer::Mode _mode { };
bool _alpha = false;
public: public:
@ -78,10 +77,9 @@ class Framebuffer::Session_component : public Rpc_object<Session>
* client calls 'dataspace' the next time, the new mode becomes * client calls 'dataspace' the next time, the new mode becomes
* effective. * effective.
*/ */
void notify_mode_change(Framebuffer::Mode mode, bool alpha) void notify_mode_change(Framebuffer::Mode mode)
{ {
_mode = mode; _mode = mode;
_alpha = alpha;
if (_mode_sigh.valid()) if (_mode_sigh.valid())
Signal_transmitter(_mode_sigh).submit(); Signal_transmitter(_mode_sigh).submit();
@ -100,7 +98,7 @@ class Framebuffer::Session_component : public Rpc_object<Session>
Dataspace_capability dataspace() override Dataspace_capability dataspace() override
{ {
return _buffer_provider.realloc_buffer(_mode, _alpha); return _buffer_provider.realloc_buffer(_mode);
} }
Mode mode() const override { return _mode; } Mode mode() const override { return _mode; }

View File

@ -384,21 +384,22 @@ Framebuffer::Mode Gui_session::mode()
* the special case of 0x0, which can happen at boot time before the * the special case of 0x0, which can happen at boot time before the
* framebuffer driver is running. * framebuffer driver is running.
*/ */
return { .area = { max(screen.w, 1u), max(screen.h, 1u) } }; return { .area = { max(screen.w, 1u), max(screen.h, 1u) },
.alpha = uses_alpha() };
} }
Gui_session::Buffer_result Gui_session::buffer(Framebuffer::Mode mode, bool use_alpha) Gui_session::Buffer_result Gui_session::buffer(Framebuffer::Mode mode)
{ {
/* check if the session quota suffices for the specified mode */ /* check if the session quota suffices for the specified mode */
if (_buffer_size + _ram_quota_guard().avail().value < ram_quota(mode, use_alpha)) if (_buffer_size + _ram_quota_guard().avail().value < ram_quota(mode))
return Buffer_result::OUT_OF_RAM; return Buffer_result::OUT_OF_RAM;
/* buffer re-allocation may consume new dataspace capability if buffer is new */ /* buffer re-allocation may consume new dataspace capability if buffer is new */
if (_cap_quota_guard().avail().value < 1) if (_cap_quota_guard().avail().value < 1)
throw Buffer_result::OUT_OF_CAPS; throw Buffer_result::OUT_OF_CAPS;
_framebuffer_session_component.notify_mode_change(mode, use_alpha); _framebuffer_session_component.notify_mode_change(mode);
return Buffer_result::OK; return Buffer_result::OK;
} }
@ -418,9 +419,9 @@ void Gui_session::focus(Capability<Gui::Session> session_cap)
} }
Dataspace_capability Gui_session::realloc_buffer(Framebuffer::Mode mode, bool use_alpha) Dataspace_capability Gui_session::realloc_buffer(Framebuffer::Mode mode)
{ {
Ram_quota const next_buffer_size { Chunky_texture<Pixel>::calc_num_bytes(mode.area, use_alpha) }; Ram_quota const next_buffer_size { Chunky_texture<Pixel>::calc_num_bytes(mode) };
Ram_quota const orig_buffer_size { _buffer_size }; Ram_quota const orig_buffer_size { _buffer_size };
/* /*
@ -439,7 +440,6 @@ Dataspace_capability Gui_session::realloc_buffer(Framebuffer::Mode mode, bool us
} }
_buffer_size = 0; _buffer_size = 0;
_uses_alpha = false;
_input_mask = nullptr; _input_mask = nullptr;
Ram_quota const temporary_ram_upgrade = _texture.valid() Ram_quota const temporary_ram_upgrade = _texture.valid()
@ -447,7 +447,7 @@ Dataspace_capability Gui_session::realloc_buffer(Framebuffer::Mode mode, bool us
_ram_quota_guard().upgrade(temporary_ram_upgrade); _ram_quota_guard().upgrade(temporary_ram_upgrade);
if (!_texture.try_construct_next(_env.ram(), _env.rm(), mode.area, use_alpha)) { if (!_texture.try_construct_next(_env.ram(), _env.rm(), mode)) {
_texture.release_current(); _texture.release_current();
replenish(orig_buffer_size); replenish(orig_buffer_size);
_ram_quota_guard().try_downgrade(temporary_ram_upgrade); _ram_quota_guard().try_downgrade(temporary_ram_upgrade);
@ -470,7 +470,6 @@ Dataspace_capability Gui_session::realloc_buffer(Framebuffer::Mode mode, bool us
} }
_buffer_size = next_buffer_size.value; _buffer_size = next_buffer_size.value;
_uses_alpha = use_alpha;
_input_mask = _texture.input_mask_buffer(); _input_mask = _texture.input_mask_buffer();
return _texture.dataspace(); return _texture.dataspace();

View File

@ -105,8 +105,7 @@ class Nitpicker::Gui_session : public Session_object<Gui::Session>,
*/ */
unsigned char const *_input_mask = nullptr; unsigned char const *_input_mask = nullptr;
bool _uses_alpha = false; bool _visible = true;
bool _visible = true;
Sliced_heap _session_alloc; Sliced_heap _session_alloc;
@ -284,7 +283,7 @@ class Nitpicker::Gui_session : public Session_object<Gui::Session>,
View const *background() const override { return _background; } View const *background() const override { return _background; }
bool uses_alpha() const override { return _texture.valid() && _uses_alpha; } bool uses_alpha() const override { return _texture.alpha(); }
unsigned layer() const override { return _domain ? _domain->layer() : ~0U; } unsigned layer() const override { return _domain ? _domain->layer() : ~0U; }
@ -407,7 +406,7 @@ class Nitpicker::Gui_session : public Session_object<Gui::Session>,
void mode_sigh(Signal_context_capability sigh) override { _mode_sigh = sigh; } void mode_sigh(Signal_context_capability sigh) override { _mode_sigh = sigh; }
Buffer_result buffer(Framebuffer::Mode, bool) override; Buffer_result buffer(Framebuffer::Mode) override;
void focus(Capability<Gui::Session>) override; void focus(Capability<Gui::Session>) override;
@ -416,7 +415,7 @@ class Nitpicker::Gui_session : public Session_object<Gui::Session>,
** Buffer_provider interface ** ** Buffer_provider interface **
*******************************/ *******************************/
Dataspace_capability realloc_buffer(Framebuffer::Mode mode, bool use_alpha) override; Dataspace_capability realloc_buffer(Framebuffer::Mode mode) override;
void blit(Rect from, Point to) override { _texture.blit(from, to); } void blit(Rect from, Point to) override { _texture.blit(from, to); }

View File

@ -47,14 +47,15 @@ class Nitpicker::Resizeable_texture
: Area { }; : Area { };
} }
bool alpha() const { return valid() && _textures[_current]->alpha(); }
void release_current() { _textures[_current].destruct(); } void release_current() { _textures[_current].destruct(); }
bool try_construct_next(Ram_allocator &ram, Region_map &rm, bool try_construct_next(Ram_allocator &ram, Region_map &rm, Framebuffer::Mode mode)
Area size, bool use_alpha)
{ {
try { try {
unsigned const next = !_current; unsigned const next = !_current;
_textures[next].construct(ram, rm, size, use_alpha); _textures[next].construct(ram, rm, mode);
return true; return true;
} catch (...) { } } catch (...) { }
return false; return false;

View File

@ -459,7 +459,7 @@ class Vmm::Virtio_gpu_device : public Virtio_device<Virtio_gpu_queue, 2>
_fb_ds.destruct(); _fb_ds.destruct();
_fb_mode = _gui.mode(); _fb_mode = _gui.mode();
_gui.buffer(_fb_mode, false); _gui.buffer(_fb_mode);
if (_fb_mode.area.count() > 0) if (_fb_mode.area.count() > 0)
_fb_ds.construct(_env.rm(), _gui.framebuffer.dataspace()); _fb_ds.construct(_env.rm(), _gui.framebuffer.dataspace());

View File

@ -66,7 +66,7 @@ struct Test::Main
} }
} }
bool _gui_buffer_init = ( _validate_mode(), _gui.buffer(_mode, false), true ); bool _gui_buffer_init = ( _validate_mode(), _gui.buffer(_mode), true );
Attached_dataspace _fb_ds { _env.rm(), _gui.framebuffer.dataspace() }; Attached_dataspace _fb_ds { _env.rm(), _gui.framebuffer.dataspace() };
@ -75,7 +75,7 @@ struct Test::Main
Output(Env &env, Allocator &alloc, Xml_node const &config) Output(Env &env, Allocator &alloc, Xml_node const &config)
: :
_env(env), _alloc(alloc), _env(env), _alloc(alloc),
_mode({ .area = _area_from_xml(config, Area { }) }) _mode({ .area = _area_from_xml(config, Area { }), .alpha = false })
{ {
auto view_rect = [&] (Xml_node node) auto view_rect = [&] (Xml_node node)
{ {

View File

@ -236,11 +236,11 @@ Test::Main::Main(Genode::Env &env) : _env(env)
Gui::Area const size { 256, 256 }; Gui::Area const size { 256, 256 };
Framebuffer::Mode const mode { .area = size }; Framebuffer::Mode const mode { .area = size, .alpha = _config.alpha };
log("screen is ", mode); log("screen is ", mode);
_gui.buffer(mode, _config.alpha); _gui.buffer(mode);
_fb_ds.construct(_env.rm(), _gui.framebuffer.dataspace()); _fb_ds.construct(_env.rm(), _gui.framebuffer.dataspace());

View File

@ -70,7 +70,7 @@ struct Test::Main
} }
} }
bool _gui_buffer_init = ( _validate_mode(), _gui.buffer(_mode, false), true ); bool _gui_buffer_init = ( _validate_mode(), _gui.buffer(_mode), true );
Attached_dataspace _fb_ds { _env.rm(), _gui.framebuffer.dataspace() }; Attached_dataspace _fb_ds { _env.rm(), _gui.framebuffer.dataspace() };
@ -79,7 +79,7 @@ struct Test::Main
Output(Env &env, Allocator &alloc, Xml_node const &config) Output(Env &env, Allocator &alloc, Xml_node const &config)
: :
_env(env), _alloc(alloc), _env(env), _alloc(alloc),
_mode({ .area = _area_from_xml(config, Area { }) }) _mode({ .area = _area_from_xml(config, Area { }), .alpha = false })
{ {
auto view_rect = [&] (Xml_node node) auto view_rect = [&] (Xml_node node)
{ {

View File

@ -66,13 +66,13 @@ class Genodefb :
size_t const max_h = Genode::min(_fb_mode.area.h, _virtual_fb_mode.area.h); size_t const max_h = Genode::min(_fb_mode.area.h, _virtual_fb_mode.area.h);
size_t const num_pixels = _fb_mode.area.w * max_h; size_t const num_pixels = _fb_mode.area.w * max_h;
memset(_fb_base, 0, num_pixels * _fb_mode.bytes_per_pixel()); memset(_fb_base, 0, num_pixels * sizeof(Genode::Pixel_rgb888));
_gui.framebuffer.refresh({ { 0, 0 }, _virtual_fb_mode.area }); _gui.framebuffer.refresh({ { 0, 0 }, _virtual_fb_mode.area });
} }
void _adjust_buffer() void _adjust_buffer()
{ {
_gui.buffer(_fb_mode, false); _gui.buffer(_fb_mode);
_view.area(_fb_mode.area); _view.area(_fb_mode.area);
} }

View File

@ -64,13 +64,13 @@ class Genodefb :
size_t const max_h = Genode::min(_fb_mode.area.h, _virtual_fb_mode.area.h); size_t const max_h = Genode::min(_fb_mode.area.h, _virtual_fb_mode.area.h);
size_t const num_pixels = _fb_mode.area.w * max_h; size_t const num_pixels = _fb_mode.area.w * max_h;
memset(_fb_base, 0, num_pixels * _fb_mode.bytes_per_pixel()); memset(_fb_base, 0, num_pixels * sizeof(Genode::Pixel_rgb888));
_gui.framebuffer.refresh({ { 0, 0 }, _virtual_fb_mode.area }); _gui.framebuffer.refresh({ { 0, 0 }, _virtual_fb_mode.area });
} }
void _adjust_buffer() void _adjust_buffer()
{ {
_gui.buffer(_fb_mode, false); _gui.buffer(_fb_mode);
_view.area(_fb_mode.area); _view.area(_fb_mode.area);
} }