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)
{
Framebuffer::Mode const mode { .area = { max_size.w, max_size.h*2 }};
_gui.buffer(mode, false);
_gui.buffer({ .area = { max_size.w, max_size.h*2 }, .alpha = false });
return _gui.framebuffer.dataspace();
}

View File

@ -239,10 +239,10 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Session>
public:
Session_component(Genode::Env &env, Window_content &window_content)
Session_component(Env &env, Window_content &window_content)
: _timer(env), _window_content(window_content) { }
Genode::Dataspace_capability dataspace() override
Dataspace_capability dataspace() override
{
_window_content.realloc_framebuffer();
return _window_content.fb_ds_cap();
@ -250,13 +250,15 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Session>
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 {
_window_content.mode_sigh(sigh); }
void mode_sigh(Signal_context_capability sigh) override
{
_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.trigger_periodic(10*1000);

View File

@ -366,7 +366,7 @@ struct Nitlog::Main
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);

View File

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

View File

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

View File

@ -59,7 +59,7 @@ struct Backdrop::Main
Dataspace_capability _ds_cap(Gui::Connection &gui)
{
/* setup virtual framebuffer mode */
gui.buffer(mode, false);
gui.buffer(mode);
return gui.framebuffer.dataspace();
}
@ -314,9 +314,11 @@ void Backdrop::Main::_handle_config()
_config.update();
Framebuffer::Mode const phys_mode = _gui.mode();
Framebuffer::Mode const
mode { .area = { _config.xml().attribute_value("width", phys_mode.area.w),
_config.xml().attribute_value("height", phys_mode.area.h) } };
Framebuffer::Mode const mode {
.area = { _config.xml().attribute_value("width", phys_mode.area.w),
_config.xml().attribute_value("height", phys_mode.area.h) },
.alpha = false
};
_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
* 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()
@ -80,7 +81,7 @@ struct Decorator::Main : Window_factory_base
:
mode(gui.mode()),
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())
{ }
};

View File

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

View File

@ -300,17 +300,15 @@ class Decorator::Window : public Window_base, public Animator::Item
void _reallocate_gui_buffers()
{
bool const use_alpha = true;
Area const size_top_bottom = _visible_top_bottom_area(geometry().area);
if (size_top_bottom.w > _size_top_bottom.w
|| size_top_bottom.h > _size_top_bottom.h
|| !_buffer_top_bottom.constructed()) {
_gui_top_bottom.buffer(Framebuffer::Mode { .area = { size_top_bottom.w,
size_top_bottom.h } },
use_alpha);
_gui_top_bottom.buffer({ .area = { size_top_bottom.w,
size_top_bottom.h },
.alpha = true });
_buffer_top_bottom.construct(_gui_top_bottom, size_top_bottom,
_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
|| !_buffer_left_right.constructed()) {
_gui_left_right.buffer(Framebuffer::Mode { .area = { size_left_right.w,
size_left_right.h } },
use_alpha);
_gui_left_right.buffer({ .area = { size_left_right.w,
size_left_right.h },
.alpha = true });
_buffer_left_right.construct(_gui_left_right, size_left_right,
_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 {
_gui_session.mode_sigh(sigh); }
Buffer_result buffer(Framebuffer::Mode mode, bool use_alpha) override {
return _gui_session.buffer(mode, use_alpha); }
Buffer_result buffer(Framebuffer::Mode mode) override {
return _gui_session.buffer(mode); }
void focus(Capability<Gui::Session> session) override {
_gui_session.focus(session); }

View File

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

View File

@ -217,7 +217,7 @@ struct Terminal::Main : Character_consumer
_gui.input.sigh(_input_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 */
_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
*/
_gui.buffer(_fb_mode, false);
_gui.buffer(_fb_mode);
if (_fb_mode.area.count() > 0)
_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);
}
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 { }

View File

@ -114,9 +114,9 @@ class Wm::Direct_gui_session : public Session_object<Gui::Session>
_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

View File

@ -1170,7 +1170,8 @@ class Wm::Gui::Session_component : public Session_object<Gui::Session>,
* mode
*/
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
@ -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 (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.
@ -1200,7 +1202,7 @@ class Wm::Gui::Session_component : public Session_object<Gui::Session>,
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
@ -1211,9 +1213,9 @@ class Wm::Gui::Session_component : public Session_object<Gui::Session>,
* wrapped GUI session. Otherwise, we would perform session
* 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();
return result;

View File

@ -107,7 +107,7 @@ struct Wm::Layouter_gui_session : Session_object<Gui::Session>
_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 { }
};

View File

@ -87,8 +87,6 @@ class Pdf_view
private:
enum { NO_ALPHA = false };
Genode::Env &_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);
if (max_x > _fb_mode.area.w || max_y > _fb_mode.area.h) {
_fb_mode = Mode { .area = { max_x, max_y } };
_gui.buffer(_fb_mode, NO_ALPHA);
_fb_mode = Mode { .area = { max_x, max_y }, .alpha = false };
_gui.buffer(_fb_mode);
if (_fb_ds.constructed())
_fb_ds.destruct();
_fb_ds.construct(_env.rm(), _gui.framebuffer.dataspace());

View File

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

View File

@ -57,13 +57,13 @@ struct Window : Genode_egl_window
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;
height = h;
type = WINDOW;
gui.buffer(mode, false);
gui.buffer(mode);
mode_change();
}

View File

@ -34,6 +34,7 @@ namespace Framebuffer {
struct Mode
{
Area area;
bool alpha;
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 {
call<Rpc_mode_sigh>(sigh); }
[[nodiscard]] Buffer_result buffer(Framebuffer::Mode mode, bool alpha) override {
return call<Rpc_buffer>(mode, alpha); }
[[nodiscard]] Buffer_result buffer(Framebuffer::Mode mode) override {
return call<Rpc_buffer>(mode); }
void focus(Gui::Session_capability session) override {
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
? needed - _ram_quota.value : 0u;
if (upgrade > 0) {
@ -166,7 +166,7 @@ class Gui::Connection : private Genode::Connection<Session>
for (bool retry = false; ; ) {
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_CAPS) { upgrade_caps(2); retry = true; }
if (!retry)

View File

@ -248,7 +248,7 @@ struct Gui::Session : Genode::Session
/**
* 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
@ -268,13 +268,13 @@ struct Gui::Session : Genode::Session
/**
* 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
* 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_sigh, void, mode_sigh, Signal_context_capability);
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,
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)
return;
Framebuffer::Mode const mode { .area = pointer_size };
_gui.buffer(mode, true /* use alpha */);
_gui.buffer({ .area = pointer_size, .alpha = true });
_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
* 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) {
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
* 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()
{
_gui.buffer(_mode, false);
_gui.buffer(_mode);
return _gui.framebuffer.dataspace();
}

View File

@ -124,7 +124,7 @@ struct Framebuffer::Session_component : Genode::Rpc_object<Framebuffer::Session>
{
/* calculation in 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,
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)
return;
Framebuffer::Mode const mode { .area = size };
Framebuffer::Mode const mode { .area = size, .alpha = false };
if (!_ram_suffices_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
{
_gui.buffer(_active_mode, false);
_gui.buffer(_active_mode);
_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
@ -294,8 +294,11 @@ struct Gui_fb::Main : View_updater
Framebuffer::Mode _initial_mode()
{
return Framebuffer::Mode { .area = { _initial_size.width (_gui.mode()),
_initial_size.height(_gui.mode()) } };
return {
.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
*
* Used by 'Framebuffer::Session_component', * implemented by 'Gui_session'
* Used by 'Framebuffer::Session_component', implemented by 'Gui_session'
*/
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;

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
*/
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 */
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(); }
@ -104,13 +105,13 @@ class Nitpicker::Chunky_texture : public Buffer, public Texture<PT>
/**
* 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)),
Texture<PT>((PT *)local_addr(),
_alpha_base(size, use_alpha), size) { }
Buffer(ram, rm, mode.area, calc_num_bytes(mode)),
Texture<PT>((PT *)local_addr(), _alpha_base(mode), mode.area)
{ }
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
@ -118,19 +119,17 @@ class Nitpicker::Chunky_texture : public Buffer, public Texture<PT>
* mask buffer. Hence, we have to account one byte per
* alpha value and one byte for the input mask value.
*/
size_t bytes_per_pixel = sizeof(PT) + (use_alpha ? 2 : 0);
return bytes_per_pixel*size.count();
size_t bytes_per_pixel = sizeof(PT) + (mode.alpha ? 2 : 0);
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;
Area const size = Texture<PT>::size();
/* input-mask values come right after the alpha values */
return (unsigned char const *)local_addr() + calc_num_bytes(size, false)
+ size.count();
Framebuffer::Mode const mode { .area = _area(), .alpha = false };
return (uint8_t const *)local_addr() + calc_num_bytes(mode) + _area().count();
}
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 _sync_sigh { };
Framebuffer::Mode _mode { };
bool _alpha = false;
public:
@ -78,10 +77,9 @@ class Framebuffer::Session_component : public Rpc_object<Session>
* client calls 'dataspace' the next time, the new mode becomes
* effective.
*/
void notify_mode_change(Framebuffer::Mode mode, bool alpha)
void notify_mode_change(Framebuffer::Mode mode)
{
_mode = mode;
_alpha = alpha;
_mode = mode;
if (_mode_sigh.valid())
Signal_transmitter(_mode_sigh).submit();
@ -100,7 +98,7 @@ class Framebuffer::Session_component : public Rpc_object<Session>
Dataspace_capability dataspace() override
{
return _buffer_provider.realloc_buffer(_mode, _alpha);
return _buffer_provider.realloc_buffer(_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
* 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 */
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;
/* buffer re-allocation may consume new dataspace capability if buffer is new */
if (_cap_quota_guard().avail().value < 1)
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;
}
@ -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 };
/*
@ -439,7 +440,6 @@ Dataspace_capability Gui_session::realloc_buffer(Framebuffer::Mode mode, bool us
}
_buffer_size = 0;
_uses_alpha = false;
_input_mask = nullptr;
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);
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();
replenish(orig_buffer_size);
_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;
_uses_alpha = use_alpha;
_input_mask = _texture.input_mask_buffer();
return _texture.dataspace();

View File

@ -105,8 +105,7 @@ class Nitpicker::Gui_session : public Session_object<Gui::Session>,
*/
unsigned char const *_input_mask = nullptr;
bool _uses_alpha = false;
bool _visible = true;
bool _visible = true;
Sliced_heap _session_alloc;
@ -284,7 +283,7 @@ class Nitpicker::Gui_session : public Session_object<Gui::Session>,
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; }
@ -407,7 +406,7 @@ class Nitpicker::Gui_session : public Session_object<Gui::Session>,
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;
@ -416,7 +415,7 @@ class Nitpicker::Gui_session : public Session_object<Gui::Session>,
** 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); }

View File

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

View File

@ -459,7 +459,7 @@ class Vmm::Virtio_gpu_device : public Virtio_device<Virtio_gpu_queue, 2>
_fb_ds.destruct();
_fb_mode = _gui.mode();
_gui.buffer(_fb_mode, false);
_gui.buffer(_fb_mode);
if (_fb_mode.area.count() > 0)
_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() };
@ -75,7 +75,7 @@ struct Test::Main
Output(Env &env, Allocator &alloc, Xml_node const &config)
:
_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)
{

View File

@ -236,11 +236,11 @@ Test::Main::Main(Genode::Env &env) : _env(env)
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);
_gui.buffer(mode, _config.alpha);
_gui.buffer(mode);
_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() };
@ -79,7 +79,7 @@ struct Test::Main
Output(Env &env, Allocator &alloc, Xml_node const &config)
:
_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)
{

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 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 });
}
void _adjust_buffer()
{
_gui.buffer(_fb_mode, false);
_gui.buffer(_fb_mode);
_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 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 });
}
void _adjust_buffer()
{
_gui.buffer(_fb_mode, false);
_gui.buffer(_fb_mode);
_view.area(_fb_mode.area);
}