mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-31 08:25:38 +00:00
menu_view: configurable alpha channel and bg color
This patch enhances menu_view with the optional configuration attributes 'opaque' and 'background'. Setting 'opaque' to "yes" suppresses the use of the alpha channel at the GUI session. This improves the drawing performance by 20% on the PinePhone. Since the menu_view uses the gems/gui_buffer.h utility, the 'Gui_buffer' received a new 'Alpha' argument at construction time. The 'background' attribute can be specified to define the reset color of the GUI buffer. It alleviates the need to create a frame widget for the top level. The patch also switches the optimization level for compiling menu_view to -O3, which increases the drawing performance on the PinePhone by 30%. Fixes #4592
This commit is contained in:
parent
bd8c7f84dd
commit
2772abc8d7
@ -48,41 +48,49 @@ struct Gui_buffer
|
|||||||
|
|
||||||
Framebuffer::Mode const mode;
|
Framebuffer::Mode const mode;
|
||||||
|
|
||||||
|
bool const use_alpha;
|
||||||
|
|
||||||
|
Pixel_rgb888 reset_color { 127, 127, 127, 255 };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return dataspace capability for virtual framebuffer
|
* Return dataspace capability for virtual framebuffer
|
||||||
*/
|
*/
|
||||||
Genode::Dataspace_capability _ds_cap(Gui::Connection &gui)
|
Genode::Dataspace_capability _ds_cap(Gui::Connection &gui)
|
||||||
{
|
{
|
||||||
/* setup virtual framebuffer mode */
|
/* setup virtual framebuffer mode */
|
||||||
gui.buffer(mode, true);
|
gui.buffer(mode, use_alpha);
|
||||||
|
|
||||||
return gui.framebuffer()->dataspace();
|
return gui.framebuffer()->dataspace();
|
||||||
}
|
}
|
||||||
|
|
||||||
Genode::Attached_dataspace fb_ds { rm, _ds_cap(gui) };
|
Genode::Attached_dataspace fb_ds { rm, _ds_cap(gui) };
|
||||||
|
|
||||||
Genode::size_t pixel_surface_num_bytes() const
|
size_t pixel_surface_num_bytes() const
|
||||||
{
|
{
|
||||||
return size().count()*sizeof(Pixel_rgb888);
|
return size().count()*sizeof(Pixel_rgb888);
|
||||||
}
|
}
|
||||||
|
|
||||||
Genode::size_t alpha_surface_num_bytes() const
|
size_t alpha_surface_num_bytes() const
|
||||||
{
|
{
|
||||||
return size().count();
|
return use_alpha ? size().count() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ram_ds pixel_surface_ds { ram, rm, pixel_surface_num_bytes() };
|
Ram_ds pixel_surface_ds { ram, rm, pixel_surface_num_bytes() };
|
||||||
Ram_ds alpha_surface_ds { ram, rm, alpha_surface_num_bytes() };
|
Ram_ds alpha_surface_ds { ram, rm, alpha_surface_num_bytes() };
|
||||||
|
|
||||||
|
enum class Alpha { OPAQUE, ALPHA };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
Gui_buffer(Gui::Connection &gui, Area size,
|
Gui_buffer(Gui::Connection &gui, Area size,
|
||||||
Genode::Ram_allocator &ram, Genode::Region_map &rm)
|
Genode::Ram_allocator &ram, Genode::Region_map &rm,
|
||||||
|
Alpha alpha = Alpha::ALPHA)
|
||||||
:
|
:
|
||||||
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)
|
||||||
{
|
{
|
||||||
reset_surface();
|
reset_surface();
|
||||||
}
|
}
|
||||||
@ -93,33 +101,48 @@ struct Gui_buffer
|
|||||||
Area size() const { return mode.area; }
|
Area size() const { return mode.area; }
|
||||||
|
|
||||||
template <typename FN>
|
template <typename FN>
|
||||||
void apply_to_surface(FN const &fn)
|
void with_alpha_surface(FN const &fn)
|
||||||
|
{
|
||||||
|
Area const alpha_size = use_alpha ? size() : Area(0, 0);
|
||||||
|
Alpha_surface alpha(alpha_surface_ds.local_addr<Pixel_alpha8>(), alpha_size);
|
||||||
|
fn(alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FN>
|
||||||
|
void with_pixel_surface(FN const &fn)
|
||||||
{
|
{
|
||||||
Pixel_surface pixel(pixel_surface_ds.local_addr<Pixel_rgb888>(), size());
|
Pixel_surface pixel(pixel_surface_ds.local_addr<Pixel_rgb888>(), size());
|
||||||
Alpha_surface alpha(alpha_surface_ds.local_addr<Pixel_alpha8>(), size());
|
fn(pixel);
|
||||||
fn(pixel, alpha);
|
}
|
||||||
|
|
||||||
|
template <typename FN>
|
||||||
|
void apply_to_surface(FN const &fn)
|
||||||
|
{
|
||||||
|
with_alpha_surface([&] (Alpha_surface &alpha) {
|
||||||
|
with_pixel_surface([&] (Pixel_surface &pixel) {
|
||||||
|
fn(pixel, alpha); }); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset_surface()
|
void reset_surface()
|
||||||
{
|
{
|
||||||
Pixel_surface pixel(pixel_surface_ds.local_addr<Pixel_rgb888>(), size());
|
if (use_alpha)
|
||||||
Alpha_surface alpha(alpha_surface_ds.local_addr<Pixel_alpha8>(), size());
|
with_alpha_surface([&] (Alpha_surface &alpha) {
|
||||||
|
Genode::memset(alpha.addr(), 0, alpha_surface_num_bytes()); });
|
||||||
|
|
||||||
Genode::size_t const num_pixels = size().count();
|
with_pixel_surface([&] (Pixel_surface &pixel) {
|
||||||
Genode::memset(alpha.addr(), 0, num_pixels);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize color buffer with 50% gray
|
* Initialize color buffer with 50% gray
|
||||||
*
|
*
|
||||||
* We do not use black to limit the bleeding of black into antialiased
|
* We do not use black to limit the bleeding of black into antialiased
|
||||||
* drawing operations applied onto an initially transparent background.
|
* drawing operations applied onto an initially transparent background.
|
||||||
*/
|
*/
|
||||||
Pixel_rgb888 *dst = pixel.addr();
|
Pixel_rgb888 *dst = pixel.addr();
|
||||||
|
Pixel_rgb888 const color = reset_color;
|
||||||
|
|
||||||
Pixel_rgb888 const gray(127, 127, 127, 255);
|
for (size_t n = size().count(); n; n--)
|
||||||
|
*dst++ = color;
|
||||||
for (size_t n = num_pixels; n; n--)
|
});
|
||||||
*dst++ = gray;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename DST_PT, typename SRC_PT>
|
template <typename DST_PT, typename SRC_PT>
|
||||||
@ -136,6 +159,9 @@ struct Gui_buffer
|
|||||||
|
|
||||||
void _update_input_mask()
|
void _update_input_mask()
|
||||||
{
|
{
|
||||||
|
if (!use_alpha)
|
||||||
|
return;
|
||||||
|
|
||||||
size_t const num_pixels = size().count();
|
size_t const num_pixels = size().count();
|
||||||
|
|
||||||
unsigned char * const alpha_base = fb_ds.local_addr<unsigned char>()
|
unsigned char * const alpha_base = fb_ds.local_addr<unsigned char>()
|
||||||
@ -159,26 +185,31 @@ struct Gui_buffer
|
|||||||
|
|
||||||
void flush_surface()
|
void flush_surface()
|
||||||
{
|
{
|
||||||
/* represent back buffer as texture */
|
|
||||||
Genode::Texture<Pixel_rgb888>
|
|
||||||
pixel_texture(pixel_surface_ds.local_addr<Pixel_rgb888>(),
|
|
||||||
nullptr, size());
|
|
||||||
|
|
||||||
Genode::Texture<Pixel_alpha8>
|
|
||||||
alpha_texture(alpha_surface_ds.local_addr<Pixel_alpha8>(),
|
|
||||||
nullptr, size());
|
|
||||||
|
|
||||||
// XXX track dirty rectangles
|
// XXX track dirty rectangles
|
||||||
Rect const clip_rect(Genode::Surface_base::Point(0, 0), size());
|
Rect const clip_rect(Genode::Surface_base::Point(0, 0), size());
|
||||||
|
|
||||||
Pixel_rgb888 *pixel_base = fb_ds.local_addr<Pixel_rgb888>();
|
{
|
||||||
Pixel_alpha8 *alpha_base = fb_ds.local_addr<Pixel_alpha8>()
|
/* represent back buffer as texture */
|
||||||
+ mode.bytes_per_pixel()*size().count();
|
Genode::Texture<Pixel_rgb888>
|
||||||
|
pixel_texture(pixel_surface_ds.local_addr<Pixel_rgb888>(),
|
||||||
|
nullptr, size());
|
||||||
|
Pixel_rgb888 *pixel_base = fb_ds.local_addr<Pixel_rgb888>();
|
||||||
|
|
||||||
_convert_back_to_front(pixel_base, pixel_texture, clip_rect);
|
_convert_back_to_front(pixel_base, pixel_texture, clip_rect);
|
||||||
_convert_back_to_front(alpha_base, alpha_texture, clip_rect);
|
}
|
||||||
|
|
||||||
_update_input_mask();
|
if (use_alpha) {
|
||||||
|
Genode::Texture<Pixel_alpha8>
|
||||||
|
alpha_texture(alpha_surface_ds.local_addr<Pixel_alpha8>(),
|
||||||
|
nullptr, size());
|
||||||
|
|
||||||
|
Pixel_alpha8 *alpha_base = fb_ds.local_addr<Pixel_alpha8>()
|
||||||
|
+ mode.bytes_per_pixel()*size().count();
|
||||||
|
|
||||||
|
_convert_back_to_front(alpha_base, alpha_texture, clip_rect);
|
||||||
|
|
||||||
|
_update_input_mask();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,6 +41,11 @@ struct Menu_view::Main
|
|||||||
|
|
||||||
Constructible<Gui_buffer> _buffer { };
|
Constructible<Gui_buffer> _buffer { };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alpha surface used when operating in opaque mode
|
||||||
|
*/
|
||||||
|
Surface<Pixel_alpha8> _no_alpha { nullptr, Area(0,0) };
|
||||||
|
|
||||||
Gui::Session::View_handle _view_handle = _gui.create_view();
|
Gui::Session::View_handle _view_handle = _gui.create_view();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -128,6 +133,10 @@ struct Menu_view::Main
|
|||||||
|
|
||||||
Attached_dataspace _input_ds { _env.rm(), _gui.input()->dataspace() };
|
Attached_dataspace _input_ds { _env.rm(), _gui.input()->dataspace() };
|
||||||
|
|
||||||
|
bool _opaque = false;
|
||||||
|
|
||||||
|
Color _background_color { };
|
||||||
|
|
||||||
Widget::Hovered _last_reported_hovered { };
|
Widget::Hovered _last_reported_hovered { };
|
||||||
|
|
||||||
void _handle_config();
|
void _handle_config();
|
||||||
@ -296,14 +305,20 @@ void Menu_view::Main::_handle_config()
|
|||||||
{
|
{
|
||||||
_config.update();
|
_config.update();
|
||||||
|
|
||||||
|
Xml_node const config = _config.xml();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
_hover_reporter.enabled(_config.xml().sub_node("report")
|
_hover_reporter.enabled(config.sub_node("report")
|
||||||
.attribute_value("hover", false));
|
.attribute_value("hover", false));
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
_hover_reporter.enabled(false);
|
_hover_reporter.enabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
_config.xml().with_sub_node("vfs", [&] (Xml_node const &vfs_node) {
|
_opaque = config.attribute_value("opaque", false);
|
||||||
|
|
||||||
|
_background_color = config.attribute_value("background", Color(127, 127, 127, 255));
|
||||||
|
|
||||||
|
config.with_sub_node("vfs", [&] (Xml_node const &vfs_node) {
|
||||||
_vfs_env.root_dir().apply_config(vfs_node); });
|
_vfs_env.root_dir().apply_config(vfs_node); });
|
||||||
|
|
||||||
_handle_dialog_update();
|
_handle_dialog_update();
|
||||||
@ -389,10 +404,17 @@ void Menu_view::Main::_handle_frame_timer()
|
|||||||
bool const size_increased = (max_size.w() > buffer_w)
|
bool const size_increased = (max_size.w() > buffer_w)
|
||||||
|| (max_size.h() > buffer_h);
|
|| (max_size.h() > buffer_h);
|
||||||
|
|
||||||
if (!_buffer.constructed() || size_increased)
|
if (!_buffer.constructed() || size_increased) {
|
||||||
_buffer.construct(_gui, max_size, _env.ram(), _env.rm());
|
_buffer.construct(_gui, max_size, _env.ram(), _env.rm(),
|
||||||
else
|
_opaque ? Gui_buffer::Alpha::OPAQUE
|
||||||
|
: Gui_buffer::Alpha::ALPHA);
|
||||||
|
_buffer->reset_color = { _background_color.r,
|
||||||
|
_background_color.g,
|
||||||
|
_background_color.b,
|
||||||
|
_background_color.a };
|
||||||
|
} else {
|
||||||
_buffer->reset_surface();
|
_buffer->reset_surface();
|
||||||
|
}
|
||||||
|
|
||||||
_root_widget.position(Point(0, 0));
|
_root_widget.position(Point(0, 0));
|
||||||
|
|
||||||
@ -400,7 +422,7 @@ void Menu_view::Main::_handle_frame_timer()
|
|||||||
// don't perform a full dialog update
|
// don't perform a full dialog update
|
||||||
_buffer->apply_to_surface([&] (Surface<Pixel_rgb888> &pixel,
|
_buffer->apply_to_surface([&] (Surface<Pixel_rgb888> &pixel,
|
||||||
Surface<Pixel_alpha8> &alpha) {
|
Surface<Pixel_alpha8> &alpha) {
|
||||||
_root_widget.draw(pixel, alpha, Point(0, 0));
|
_root_widget.draw(pixel, _opaque ? _no_alpha : alpha, Point(0, 0));
|
||||||
});
|
});
|
||||||
|
|
||||||
_buffer->flush_surface();
|
_buffer->flush_surface();
|
||||||
|
@ -3,6 +3,8 @@ SRC_CC = main.cc
|
|||||||
LIBS = base libc libm vfs libpng zlib blit file
|
LIBS = base libc libm vfs libpng zlib blit file
|
||||||
INC_DIR += $(PRG_DIR)
|
INC_DIR += $(PRG_DIR)
|
||||||
|
|
||||||
|
CC_OLEVEL := -O3
|
||||||
|
|
||||||
CUSTOM_TARGET_DEPS += menu_view_styles.tar
|
CUSTOM_TARGET_DEPS += menu_view_styles.tar
|
||||||
|
|
||||||
BUILD_ARTIFACTS := $(TARGET) menu_view_styles.tar
|
BUILD_ARTIFACTS := $(TARGET) menu_view_styles.tar
|
||||||
|
Loading…
x
Reference in New Issue
Block a user