mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-18 21:27:56 +00:00
framebuffer_session: accessors for buffer surfaces
This patch adds central and safe utilities for accessing the distinct parts of the virtual framebuffer to relieve clients from pointer calculations. Issue #5351
This commit is contained in:
parent
388218a3f9
commit
5b4e1915d8
@ -15,14 +15,8 @@
|
||||
#define _INCLUDE__GEMS__GUI_BUFFER_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/ram_allocator.h>
|
||||
#include <gui_session/connection.h>
|
||||
#include <base/attached_dataspace.h>
|
||||
#include <base/attached_ram_dataspace.h>
|
||||
#include <os/surface.h>
|
||||
#include <os/pixel_alpha8.h>
|
||||
#include <os/pixel_rgb888.h>
|
||||
#include <blit/painter.h>
|
||||
|
||||
|
||||
struct Gui_buffer : Genode::Noncopyable
|
||||
@ -38,76 +32,36 @@ struct Gui_buffer : Genode::Noncopyable
|
||||
using size_t = Genode::size_t;
|
||||
using uint8_t = Genode::uint8_t;
|
||||
|
||||
Genode::Ram_allocator &ram;
|
||||
Genode::Region_map &rm;
|
||||
Genode::Ram_allocator &_ram;
|
||||
Genode::Region_map &_rm;
|
||||
|
||||
Gui::Connection &gui;
|
||||
Gui::Connection &_gui;
|
||||
|
||||
Framebuffer::Mode const mode;
|
||||
|
||||
/*
|
||||
* Make the GUI mode twice as high as the requested mode. The upper part
|
||||
* of the GUI framebuffer contains the front buffer, the lower part
|
||||
* contains the back buffer.
|
||||
*/
|
||||
Framebuffer::Mode const _gui_mode { .area = { mode.area.w, mode.area.h*2 },
|
||||
.alpha = mode.alpha };
|
||||
|
||||
Genode::Surface_window const _backbuffer { .y = mode.area.h, .h = mode.area.h };
|
||||
|
||||
Pixel_rgb888 const reset_color;
|
||||
|
||||
/**
|
||||
* Return dataspace capability for virtual framebuffer
|
||||
*/
|
||||
Genode::Dataspace_capability _ds_cap(Gui::Connection &gui)
|
||||
{
|
||||
/*
|
||||
* 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 },
|
||||
.alpha = mode.alpha });
|
||||
|
||||
return gui.framebuffer.dataspace();
|
||||
}
|
||||
|
||||
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 mode.alpha ? size().count() : 0; }
|
||||
size_t _input_num_bytes() const { return mode.alpha ? size().count() : 0; }
|
||||
|
||||
void _with_pixel_ptr(auto const &fn)
|
||||
{
|
||||
/* skip pixel front buffer */
|
||||
uint8_t * const ptr = _fb_ds.local_addr<uint8_t>() + _pixel_num_bytes();
|
||||
fn((Pixel_rgb888 *)ptr);
|
||||
}
|
||||
|
||||
void _with_alpha_ptr(auto const &fn)
|
||||
{
|
||||
if (!mode.alpha)
|
||||
return;
|
||||
|
||||
/* skip pixel front buffer, pixel back buffer, and alpha front buffer */
|
||||
uint8_t * const ptr = _fb_ds.local_addr<uint8_t>()
|
||||
+ _pixel_num_bytes()*2 + _alpha_num_bytes();
|
||||
fn((Pixel_alpha8 *)ptr);
|
||||
}
|
||||
|
||||
void _with_input_ptr(auto const &fn)
|
||||
{
|
||||
if (!mode.alpha)
|
||||
return;
|
||||
|
||||
/* skip pixel buffers, alpha buffers, and input front buffer */
|
||||
uint8_t * const ptr = _fb_ds.local_addr<uint8_t>()
|
||||
+ _pixel_num_bytes()*2 + _alpha_num_bytes()*2 + _input_num_bytes();
|
||||
fn(ptr);
|
||||
}
|
||||
Genode::Attached_dataspace _fb_ds {
|
||||
_rm, ( _gui.buffer(_gui_mode), _gui.framebuffer.dataspace() ) };
|
||||
|
||||
enum class Alpha { OPAQUE, ALPHA };
|
||||
|
||||
static Genode::Color default_reset_color()
|
||||
{
|
||||
/*
|
||||
* Do not use black by default to limit the bleeding of black into
|
||||
* antialiased drawing operations applied onto an initially transparent
|
||||
* background.
|
||||
*/
|
||||
return Genode::Color(127, 127, 127, 255);
|
||||
}
|
||||
/*
|
||||
* Do not use black by default to limit the bleeding of black into
|
||||
* antialiased drawing operations applied onto an initially transparent
|
||||
* background.
|
||||
*/
|
||||
static constexpr Genode::Color default_reset_color = { 127, 127, 127, 255 };
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@ -115,9 +69,9 @@ struct Gui_buffer : Genode::Noncopyable
|
||||
Gui_buffer(Gui::Connection &gui, Area size,
|
||||
Genode::Ram_allocator &ram, Genode::Region_map &rm,
|
||||
Alpha alpha = Alpha::ALPHA,
|
||||
Genode::Color reset_color = default_reset_color())
|
||||
Genode::Color reset_color = default_reset_color)
|
||||
:
|
||||
ram(ram), rm(rm), gui(gui),
|
||||
_ram(ram), _rm(rm), _gui(gui),
|
||||
mode({ .area = { Genode::max(1U, size.w),
|
||||
Genode::max(1U, size.h) },
|
||||
.alpha = (alpha == Alpha::ALPHA) }),
|
||||
@ -133,16 +87,21 @@ struct Gui_buffer : Genode::Noncopyable
|
||||
|
||||
void with_alpha_surface(auto const &fn)
|
||||
{
|
||||
_with_alpha_ptr([&] (Pixel_alpha8 *ptr) {
|
||||
Alpha_surface alpha { ptr, size() };
|
||||
fn(alpha); });
|
||||
if (!_gui_mode.alpha) {
|
||||
Alpha_surface dummy { nullptr, Gui::Area { } };
|
||||
fn(dummy);
|
||||
return;
|
||||
}
|
||||
_gui_mode.with_alpha_surface(_fb_ds, [&] (Alpha_surface &surface) {
|
||||
surface.with_window(_backbuffer, [&] (Alpha_surface &surface) {
|
||||
fn(surface); }); });
|
||||
}
|
||||
|
||||
void with_pixel_surface(auto const &fn)
|
||||
{
|
||||
_with_pixel_ptr([&] (Pixel_rgb888 *ptr) {
|
||||
Pixel_surface pixel { ptr, size() };
|
||||
fn(pixel); });
|
||||
_gui_mode.with_pixel_surface(_fb_ds, [&] (Pixel_surface &surface) {
|
||||
surface.with_window(_backbuffer, [&] (Pixel_surface &surface) {
|
||||
fn(surface); }); });
|
||||
}
|
||||
|
||||
void apply_to_surface(auto const &fn)
|
||||
@ -155,7 +114,7 @@ struct Gui_buffer : Genode::Noncopyable
|
||||
void reset_surface()
|
||||
{
|
||||
with_alpha_surface([&] (Alpha_surface &alpha) {
|
||||
Genode::memset(alpha.addr(), 0, _alpha_num_bytes()); });
|
||||
Genode::memset(alpha.addr(), 0, alpha.size().count()); });
|
||||
|
||||
with_pixel_surface([&] (Pixel_surface &pixel) {
|
||||
|
||||
@ -169,20 +128,28 @@ struct Gui_buffer : Genode::Noncopyable
|
||||
|
||||
void _update_input_mask()
|
||||
{
|
||||
_with_alpha_ptr([&] (Pixel_alpha8 const * const alpha_ptr) {
|
||||
_with_input_ptr([&] (uint8_t *dst) {
|
||||
with_alpha_surface([&] (Alpha_surface &alpha) {
|
||||
|
||||
/*
|
||||
* Set input mask for all pixels where the alpha value is above
|
||||
* a given threshold. The threshold is defined such that
|
||||
* typical drop shadows are below the value.
|
||||
*/
|
||||
uint8_t const threshold = 100;
|
||||
uint8_t const * src = (uint8_t const *)alpha_ptr;
|
||||
size_t const num_pixels = size().count();
|
||||
using Input_surface = Genode::Surface<Genode::Pixel_input8>;
|
||||
|
||||
for (unsigned i = 0; i < num_pixels; i++)
|
||||
*dst++ = (*src++) > threshold;
|
||||
_gui_mode.with_input_surface(_fb_ds, [&] (Input_surface &input) {
|
||||
input.with_window(_backbuffer, [&] (Input_surface &input) {
|
||||
|
||||
uint8_t const * src = (uint8_t *)alpha.addr();
|
||||
uint8_t * dst = (uint8_t *)input.addr();
|
||||
|
||||
/*
|
||||
* Set input mask for all pixels where the alpha value is
|
||||
* above a given threshold. The threshold is defined such
|
||||
* that typical drop shadows are below the value.
|
||||
*/
|
||||
uint8_t const threshold = 100;
|
||||
size_t const num_pixels = Genode::min(alpha.size().count(),
|
||||
input.size().count());
|
||||
|
||||
for (unsigned i = 0; i < num_pixels; i++)
|
||||
*dst++ = (*src++) > threshold;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -192,7 +159,7 @@ struct Gui_buffer : Genode::Noncopyable
|
||||
_update_input_mask();
|
||||
|
||||
/* copy lower part of virtual framebuffer to upper part */
|
||||
gui.framebuffer.blit({ { 0, int(size().h) }, size() }, { 0, 0 });
|
||||
_gui.framebuffer.blit({ { 0, int(size().h) }, size() }, { 0, 0 });
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -66,11 +66,6 @@ struct Backdrop::Main
|
||||
|
||||
Attached_dataspace fb_ds;
|
||||
|
||||
Genode::size_t surface_num_bytes() const
|
||||
{
|
||||
return size().count()*mode.bytes_per_pixel();
|
||||
}
|
||||
|
||||
Attached_ram_dataspace surface_ds;
|
||||
|
||||
/**
|
||||
@ -79,7 +74,7 @@ struct Backdrop::Main
|
||||
Buffer(Genode::Env &env, Gui::Connection &gui, Framebuffer::Mode mode)
|
||||
: gui(gui), mode(mode),
|
||||
fb_ds(env.rm(), _ds_cap(gui)),
|
||||
surface_ds(env.ram(), env.rm(), surface_num_bytes())
|
||||
surface_ds(env.ram(), env.rm(), mode.num_bytes())
|
||||
{ }
|
||||
|
||||
/**
|
||||
@ -100,11 +95,10 @@ struct Backdrop::Main
|
||||
void flush_surface()
|
||||
{
|
||||
/* blit back to front buffer */
|
||||
blit(surface_ds.local_addr<void>(),
|
||||
(unsigned)surface_num_bytes(),
|
||||
fb_ds.local_addr<void>(),
|
||||
(unsigned)surface_num_bytes(),
|
||||
(unsigned)surface_num_bytes(), 1);
|
||||
unsigned const num_bytes = unsigned(mode.num_bytes());
|
||||
blit(surface_ds.local_addr<void>(), num_bytes,
|
||||
fb_ds.local_addr<void>(), num_bytes,
|
||||
num_bytes, 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -286,8 +286,6 @@ class Decorator::Window : public Window_base, public Animator::Item
|
||||
});
|
||||
|
||||
buffer.flush_surface();
|
||||
|
||||
buffer.gui.framebuffer.refresh({ { 0, 0 }, buffer.size() });
|
||||
}
|
||||
|
||||
void _repaint_decorations()
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include <dataspace/capability.h>
|
||||
#include <session/session.h>
|
||||
#include <os/surface.h>
|
||||
#include <os/pixel_rgb888.h>
|
||||
#include <os/pixel_alpha8.h>
|
||||
|
||||
namespace Framebuffer {
|
||||
|
||||
@ -36,9 +38,66 @@ namespace Framebuffer {
|
||||
Area area;
|
||||
bool alpha;
|
||||
|
||||
size_t bytes_per_pixel() const { return 4; }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, area); }
|
||||
|
||||
/*
|
||||
* If using an alpha channel, the alpha buffer follows the pixel
|
||||
* buffer. The alpha buffer is followed by an input-mask buffer.
|
||||
*
|
||||
* The input-mask buffer contains 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.
|
||||
*/
|
||||
|
||||
void with_pixel_surface(auto &ds, auto const &fn) const
|
||||
{
|
||||
Surface<Pixel_rgb888> surface { ds.bytes(), area };
|
||||
fn(surface);
|
||||
}
|
||||
|
||||
void with_alpha_bytes(auto &ds, auto const &fn) const
|
||||
{
|
||||
if (!alpha)
|
||||
return;
|
||||
|
||||
size_t const offset = area.count()*sizeof(Pixel_rgb888);
|
||||
ds.bytes().with_skipped_bytes(offset, [&] (Byte_range_ptr const &bytes) {
|
||||
fn(bytes); });
|
||||
}
|
||||
|
||||
void with_alpha_surface(auto &ds, auto const &fn) const
|
||||
{
|
||||
with_alpha_bytes(ds, [&] (Byte_range_ptr const &bytes) {
|
||||
Surface<Pixel_alpha8> surface { bytes, area };
|
||||
fn(surface); });
|
||||
}
|
||||
|
||||
void with_input_bytes(auto &ds, auto const &fn) const
|
||||
{
|
||||
if (!alpha)
|
||||
return;
|
||||
|
||||
size_t const offset = area.count()*sizeof(Pixel_rgb888) + area.count();
|
||||
ds.bytes().with_skipped_bytes(offset, [&] (Byte_range_ptr const &bytes) {
|
||||
fn(bytes); });
|
||||
}
|
||||
|
||||
void with_input_surface(auto &ds, auto const &fn) const
|
||||
{
|
||||
with_input_bytes(ds, [&] (Byte_range_ptr const &bytes) {
|
||||
Surface<Pixel_input8> surface { bytes, area };
|
||||
fn(surface); });
|
||||
}
|
||||
|
||||
size_t num_bytes() const
|
||||
{
|
||||
size_t const bytes_per_pixel =
|
||||
sizeof(Pixel_rgb888) + alpha*(sizeof(Pixel_alpha8) + sizeof(Pixel_input8));
|
||||
|
||||
return area.count()*bytes_per_pixel;
|
||||
}
|
||||
};
|
||||
|
||||
struct Transfer
|
||||
|
@ -274,7 +274,7 @@ struct Gui::Session : Genode::Session
|
||||
* 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*mode.alpha)*mode.area.count();
|
||||
return (sizeof(Pixel_rgb888) + 2*mode.alpha)*mode.area.count();
|
||||
}
|
||||
|
||||
|
||||
|
@ -126,15 +126,32 @@ class Genode::Surface : public Surface_base
|
||||
|
||||
PT *_addr; /* base address of pixel buffer */
|
||||
|
||||
static Area _sanitized(Area area, size_t const num_bytes)
|
||||
{
|
||||
/* prevent division by zero */
|
||||
if (area.w == 0)
|
||||
return { };
|
||||
|
||||
size_t const bytes_per_line = area.w*sizeof(PT);
|
||||
|
||||
return { .w = area.w,
|
||||
.h = unsigned(min(num_bytes/bytes_per_line, area.h)) };
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
PT *addr() { return _addr; }
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
/*
|
||||
* \deprecated
|
||||
*/
|
||||
Surface(PT *addr, Area size)
|
||||
: Surface_base(size, PT::format()), _addr(addr) { }
|
||||
Surface(PT *addr, Area size) : Surface_base(size, PT::format()), _addr(addr) { }
|
||||
|
||||
Surface(Byte_range_ptr const &bytes, Area const area)
|
||||
:
|
||||
Surface_base(_sanitized(area, bytes.num_bytes), PT::format()),
|
||||
_addr((PT *)bytes.start)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Call 'fn' with a sub-window surface as argument
|
||||
|
@ -25,33 +25,22 @@
|
||||
namespace Nitpicker { class Buffer; }
|
||||
|
||||
|
||||
class Nitpicker::Buffer
|
||||
struct Nitpicker::Buffer : private Attached_ram_dataspace
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Constructor - allocate and map dataspace for virtual frame buffer
|
||||
*
|
||||
* \throw Out_of_ram
|
||||
* \throw Out_of_caps
|
||||
* \throw Region_map::Region_conflict
|
||||
*/
|
||||
Buffer(Ram_allocator &ram, Region_map &rm, size_t num_bytes)
|
||||
:
|
||||
Attached_ram_dataspace(ram, rm, num_bytes)
|
||||
{ }
|
||||
|
||||
Area _size;
|
||||
Attached_ram_dataspace _ram_ds;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor - allocate and map dataspace for virtual frame buffer
|
||||
*
|
||||
* \throw Out_of_ram
|
||||
* \throw Out_of_caps
|
||||
* \throw Region_map::Region_conflict
|
||||
*/
|
||||
Buffer(Ram_allocator &ram, Region_map &rm, Area size, size_t bytes)
|
||||
:
|
||||
_size(size), _ram_ds(ram, rm, bytes)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Accessors
|
||||
*/
|
||||
Ram_dataspace_capability ds_cap() const { return _ram_ds.cap(); }
|
||||
Area size() const { return _size; }
|
||||
void *local_addr() const { return _ram_ds.local_addr<void>(); }
|
||||
using Attached_ram_dataspace::bytes;
|
||||
using Attached_ram_dataspace::cap;
|
||||
};
|
||||
|
||||
|
||||
|
@ -15,8 +15,6 @@
|
||||
#define _CHUNKY_TEXTURE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <os/pixel_rgb888.h>
|
||||
#include <os/pixel_alpha8.h>
|
||||
#include <blit/painter.h>
|
||||
|
||||
/* local includes */
|
||||
@ -26,69 +24,36 @@ namespace Nitpicker { template <typename> class Chunky_texture; }
|
||||
|
||||
|
||||
template <typename PT>
|
||||
class Nitpicker::Chunky_texture : public Buffer, public Texture<PT>
|
||||
class Nitpicker::Chunky_texture : Buffer, public Texture<PT>
|
||||
{
|
||||
private:
|
||||
|
||||
Framebuffer::Mode const _mode;
|
||||
|
||||
/**
|
||||
* Return base address of alpha channel or 0 if no alpha channel exists
|
||||
*/
|
||||
unsigned char *_alpha_base(Framebuffer::Mode mode)
|
||||
static uint8_t *_alpha_base(Buffer &buffer, Framebuffer::Mode mode)
|
||||
{
|
||||
if (!mode.alpha) return nullptr;
|
||||
|
||||
/* alpha values come right after the pixel values */
|
||||
return (unsigned char *)local_addr()
|
||||
+ calc_num_bytes({ .area = mode.area, .alpha = false });
|
||||
}
|
||||
|
||||
Area _area() const { return Texture<PT>::size(); }
|
||||
|
||||
void _with_pixel_surface(auto const &fn)
|
||||
{
|
||||
Surface<Pixel_rgb888> pixel { (Pixel_rgb888 *)local_addr(), _area() };
|
||||
fn(pixel);
|
||||
}
|
||||
|
||||
static void _with_alpha_ptr(auto &obj, auto const &fn)
|
||||
{
|
||||
Pixel_alpha8 * const ptr = (Pixel_alpha8 *)(obj.Texture<PT>::alpha());
|
||||
if (ptr)
|
||||
fn(ptr);
|
||||
}
|
||||
|
||||
void _with_alpha_surface(auto const &fn)
|
||||
{
|
||||
_with_alpha_ptr(*this, [&] (Pixel_alpha8 * const ptr) {
|
||||
Surface<Pixel_alpha8> alpha { ptr, _area() };
|
||||
fn(alpha); });
|
||||
uint8_t *result = nullptr;
|
||||
mode.with_alpha_bytes(buffer, [&] (Byte_range_ptr const &bytes) {
|
||||
result = (uint8_t *)bytes.start; });
|
||||
return result;
|
||||
}
|
||||
|
||||
void _with_alpha_texture(auto const &fn) const
|
||||
{
|
||||
_with_alpha_ptr(*this, [&] (Pixel_alpha8 * const ptr) {
|
||||
Texture<Pixel_alpha8> texture { ptr, nullptr, _area() };
|
||||
Buffer const &buffer = *this;
|
||||
_mode.with_alpha_bytes(buffer, [&] (Byte_range_ptr const &bytes) {
|
||||
Texture<Pixel_alpha8> texture { (Pixel_alpha8 *)bytes.start, nullptr, _mode.area };
|
||||
fn(texture); });
|
||||
}
|
||||
|
||||
static void _with_input_ptr(auto &obj, auto const &fn)
|
||||
{
|
||||
Pixel_alpha8 * const ptr = (Pixel_alpha8 *)(obj.input_mask_buffer());
|
||||
if (ptr)
|
||||
fn(ptr);
|
||||
}
|
||||
|
||||
void _with_input_surface(auto const &fn)
|
||||
{
|
||||
_with_input_ptr(*this, [&] (Pixel_alpha8 * const ptr) {
|
||||
Surface<Pixel_alpha8> input { ptr, _area() };
|
||||
fn(input); });
|
||||
}
|
||||
|
||||
void _with_input_texture(auto const &fn) const
|
||||
{
|
||||
_with_input_ptr(*this, [&] (Pixel_alpha8 * const ptr) {
|
||||
Texture<Pixel_alpha8> texture { ptr, nullptr, _area() };
|
||||
Buffer const &buffer = *this;
|
||||
_mode.with_input_bytes(buffer, [&] (Byte_range_ptr const &bytes) {
|
||||
Texture<Pixel_input8> texture { (Pixel_input8 *)bytes.start, nullptr, _mode.area };
|
||||
fn(texture); });
|
||||
}
|
||||
|
||||
@ -102,47 +67,36 @@ class Nitpicker::Chunky_texture : public Buffer, public Texture<PT>
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
using Buffer::cap;
|
||||
|
||||
Chunky_texture(Ram_allocator &ram, Region_map &rm, Framebuffer::Mode mode)
|
||||
:
|
||||
Buffer(ram, rm, mode.area, calc_num_bytes(mode)),
|
||||
Texture<PT>((PT *)local_addr(), _alpha_base(mode), mode.area)
|
||||
Buffer(ram, rm, mode.num_bytes()),
|
||||
Texture<PT>((PT *)Buffer::bytes().start, _alpha_base(*this, mode), mode.area),
|
||||
_mode(mode)
|
||||
{ }
|
||||
|
||||
static size_t calc_num_bytes(Framebuffer::Mode mode)
|
||||
void with_input_mask(auto const &fn) const
|
||||
{
|
||||
/*
|
||||
* If using an alpha channel, the alpha buffer follows the
|
||||
* pixel buffer. The alpha buffer is followed by an input
|
||||
* 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) + (mode.alpha ? 2 : 0);
|
||||
return bytes_per_pixel*mode.area.count();
|
||||
}
|
||||
|
||||
uint8_t const *input_mask_buffer() const
|
||||
{
|
||||
if (!Texture<PT>::alpha()) return 0;
|
||||
|
||||
/* input-mask values come right after the alpha values */
|
||||
Framebuffer::Mode const mode { .area = _area(), .alpha = false };
|
||||
return (uint8_t const *)local_addr() + calc_num_bytes(mode) + _area().count();
|
||||
Buffer const &buffer = *this;
|
||||
_mode.with_input_bytes(buffer, [&] (Byte_range_ptr const &bytes) {
|
||||
Const_byte_range_ptr const_bytes { bytes.start, bytes.num_bytes };
|
||||
fn(const_bytes); });
|
||||
}
|
||||
|
||||
void blit(Rect from, Point to)
|
||||
{
|
||||
_with_pixel_surface([&] (Surface<Pixel_rgb888> &surface) {
|
||||
Buffer &buffer = *this;
|
||||
|
||||
_mode.with_pixel_surface(buffer, [&] (Surface<Pixel_rgb888> &surface) {
|
||||
_blit_channel(surface, *this, from, to); });
|
||||
|
||||
_with_alpha_surface([&] (Surface<Pixel_alpha8> &surface) {
|
||||
_mode.with_alpha_surface(buffer, [&] (Surface<Pixel_alpha8> &surface) {
|
||||
_with_alpha_texture([&] (Texture<Pixel_alpha8> &texture) {
|
||||
_blit_channel(surface, texture, from, to); }); });
|
||||
|
||||
_with_input_surface([&] (Surface<Pixel_alpha8> &surface) {
|
||||
_with_input_texture([&] (Texture<Pixel_alpha8> &texture) {
|
||||
_mode.with_input_surface(buffer, [&] (Surface<Pixel_input8> &surface) {
|
||||
_with_input_texture([&] (Texture<Pixel_input8> &texture) {
|
||||
_blit_channel(surface, texture, from, to); }); });
|
||||
}
|
||||
};
|
||||
|
@ -421,7 +421,7 @@ void Gui_session::focus(Capability<Gui::Session> session_cap)
|
||||
|
||||
Dataspace_capability Gui_session::realloc_buffer(Framebuffer::Mode mode)
|
||||
{
|
||||
Ram_quota const next_buffer_size { Chunky_texture<Pixel>::calc_num_bytes(mode) };
|
||||
Ram_quota const next_buffer_size { mode.num_bytes() };
|
||||
Ram_quota const orig_buffer_size { _buffer_size };
|
||||
|
||||
/*
|
||||
@ -440,7 +440,6 @@ Dataspace_capability Gui_session::realloc_buffer(Framebuffer::Mode mode)
|
||||
}
|
||||
|
||||
_buffer_size = 0;
|
||||
_input_mask = nullptr;
|
||||
|
||||
Ram_quota const temporary_ram_upgrade = _texture.valid()
|
||||
? next_buffer_size : Ram_quota{0};
|
||||
@ -470,7 +469,6 @@ Dataspace_capability Gui_session::realloc_buffer(Framebuffer::Mode mode)
|
||||
}
|
||||
|
||||
_buffer_size = next_buffer_size.value;
|
||||
_input_mask = _texture.input_mask_buffer();
|
||||
|
||||
return _texture.dataspace();
|
||||
}
|
||||
|
@ -94,17 +94,6 @@ class Nitpicker::Gui_session : public Session_object<Gui::Session>,
|
||||
Domain_registry::Entry const *_domain = nullptr;
|
||||
View *_background = nullptr;
|
||||
|
||||
/*
|
||||
* The 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.
|
||||
*/
|
||||
unsigned char const *_input_mask = nullptr;
|
||||
|
||||
bool _visible = true;
|
||||
|
||||
Sliced_heap _session_alloc;
|
||||
@ -289,20 +278,22 @@ class Nitpicker::Gui_session : public Session_object<Gui::Session>,
|
||||
|
||||
bool origin_pointer() const override { return _domain && _domain->origin_pointer(); }
|
||||
|
||||
|
||||
/**
|
||||
* Return input mask value at specified buffer position
|
||||
*/
|
||||
unsigned char input_mask_at(Point p) const override
|
||||
bool input_mask_at(Point const p) const override
|
||||
{
|
||||
if (!_input_mask || !_texture.valid()) return 0;
|
||||
bool result = false;
|
||||
_texture.with_input_mask([&] (Const_byte_range_ptr const &bytes) {
|
||||
|
||||
/* check boundaries */
|
||||
if ((unsigned)p.x >= _texture.size().w
|
||||
|| (unsigned)p.y >= _texture.size().h)
|
||||
return 0;
|
||||
unsigned const x = p.x % _texture.size().w,
|
||||
y = p.y % _texture.size().h;
|
||||
|
||||
return _input_mask[p.y*_texture.size().w + p.x];
|
||||
size_t const offset = y*_texture.size().w + x;
|
||||
if (offset < bytes.num_bytes)
|
||||
result = bytes.start[offset];
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
void submit_input_event(Input::Event e) override;
|
||||
|
@ -105,13 +105,13 @@ class Nitpicker::Resizeable_texture
|
||||
|
||||
Dataspace_capability dataspace()
|
||||
{
|
||||
return valid() ? _textures[_current]->ds_cap() : Ram_dataspace_capability();
|
||||
return valid() ? _textures[_current]->cap() : Ram_dataspace_capability();
|
||||
}
|
||||
|
||||
unsigned char const *input_mask_buffer() const
|
||||
void with_input_mask(auto const &fn) const
|
||||
{
|
||||
return valid() ? _textures[_current]->input_mask_buffer()
|
||||
: nullptr;
|
||||
if (valid())
|
||||
_textures[_current]->with_input_mask(fn);
|
||||
}
|
||||
|
||||
void blit(Rect from, Point to)
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include <util/xml_node.h>
|
||||
#include <util/color.h>
|
||||
#include <base/allocator.h>
|
||||
#include <os/pixel_rgb888.h>
|
||||
#include <gui_session/gui_session.h>
|
||||
|
||||
namespace Nitpicker {
|
||||
|
@ -11,8 +11,6 @@
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#include <os/pixel_rgb888.h>
|
||||
|
||||
#include <nitpicker_gfx/texture_painter.h>
|
||||
#include <nitpicker_gfx/box_painter.h>
|
||||
|
||||
|
@ -82,7 +82,7 @@ struct Nitpicker::View_owner : Interface
|
||||
/**
|
||||
* Return input-mask value at given position
|
||||
*/
|
||||
virtual unsigned char input_mask_at(Point) const { return 0; }
|
||||
virtual bool input_mask_at(Point) const { return false; }
|
||||
|
||||
virtual void submit_input_event(Input::Event) { }
|
||||
|
||||
|
@ -107,7 +107,7 @@ struct Blit_test : Test
|
||||
{
|
||||
unsigned kib = 0;
|
||||
uint64_t const start_ms = timer.elapsed_ms();
|
||||
unsigned const w = (unsigned)(fb_mode.area.w * fb_mode.bytes_per_pixel());
|
||||
unsigned const w = unsigned(fb_mode.area.w * sizeof(Pixel_rgb888));
|
||||
unsigned const h = fb_mode.area.h;
|
||||
for (unsigned i = 0; timer.elapsed_ms() - start_ms < DURATION_MS; i++) {
|
||||
blit(buf[i % 2], w, fb_ds.local_addr<char>(), w, w, h);
|
||||
@ -125,7 +125,7 @@ struct Unaligned_blit_test : Test
|
||||
{
|
||||
unsigned kib = 0;
|
||||
uint64_t const start_ms = timer.elapsed_ms();
|
||||
unsigned const w = (unsigned)(fb_mode.area.w * fb_mode.bytes_per_pixel());
|
||||
unsigned const w = unsigned(fb_mode.area.w * sizeof(Pixel_rgb888));
|
||||
unsigned const h = fb_mode.area.h;
|
||||
for (unsigned i = 0; timer.elapsed_ms() - start_ms < DURATION_MS; i++) {
|
||||
blit(buf[i % 2] + 2, w, fb_ds.local_addr<char>() + 2, w, w - 2, h);
|
||||
|
Loading…
Reference in New Issue
Block a user