Files
genode/repos/dde_linux/src/drivers/framebuffer/imx8/include/component.h
Norman Feske ef741ef80d Change pixel format to 32 bits per pixel
Until now, Genode's framebuffer session interface was based on the
RGB565 pixel format. This patch changes the pixel format to 32-bit
XRGB where the X part is ignored. It adapts all graphical applications
and device drivers accordingly.

The patch also adjusts the users of the drivers_interactive packages,
assigning 64 MiB RAM and 1500 caps to the drivers subsystem, which is
sufficient for covering high resolutions at 32 bits per pixel and to
accommodate multi-component USB HID input stacks.

Fixes #3784
2020-06-29 14:22:29 +02:00

224 lines
5.7 KiB
C++

/*
* \brief i.MX8 framebuffer driver session component
* \author Stefan Kalkowski
* \author Christian Prochaska
* \date 2015-10-16
*/
/*
* Copyright (C) 2015-2019 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef __COMPONENT_H__
#define __COMPONENT_H__
/* Genode includes */
#include <base/component.h>
#include <base/rpc_server.h>
#include <root/component.h>
#include <dataspace/capability.h>
#include <framebuffer_session/framebuffer_session.h>
#include <timer_session/connection.h>
#include <util/reconstructible.h>
#include <base/attached_dataspace.h>
#include <base/attached_ram_dataspace.h>
#include <base/attached_rom_dataspace.h>
#include <os/reporter.h>
#include <os/pixel_rgb888.h>
#include <blit/blit.h>
#include <lx_emul_c.h>
namespace Framebuffer {
class Driver;
class Session_component;
class Root;
}
class Framebuffer::Driver
{
private:
struct Configuration
{
struct lx_c_fb_config _lx = { 16, 64, 64, 4,
nullptr, 0, nullptr };
} _config;
Session_component &_session;
Timer::Connection _timer;
Genode::Reporter _reporter;
Genode::Signal_context_capability _config_sigh;
drm_display_mode * _preferred_mode(drm_connector *connector,
unsigned &brightness);
public:
Driver(Genode::Env & env, Session_component &session)
: _session(session), _timer(env),
_reporter(env, "connectors") {}
int width() const { return _config._lx.width; }
int height() const { return _config._lx.height; }
int bpp() const { return _config._lx.bpp; }
void * fb_addr() const { return _config._lx.addr; }
unsigned pitch() const { return _config._lx.pitch; }
void finish_initialization();
void update_mode();
void generate_report();
/**
* Register signal handler used for config updates
*
* The signal handler is artificially triggered as a side effect
* of connector changes.
*/
void config_sigh(Genode::Signal_context_capability sigh)
{
_config_sigh = sigh;
}
void trigger_reconfiguration()
{
/*
* Trigger the reprocessing of the configuration following the
* same ontrol flow as used for external config changes.
*/
if (_config_sigh.valid())
Genode::Signal_transmitter(_config_sigh).submit();
else
Genode::warning("config signal handler unexpectedly undefined");
}
};
class Framebuffer::Session_component : public Genode::Rpc_object<Session>
{
private:
template <typename T> using Lazy = Genode::Constructible<T>;
Driver _driver;
Genode::Attached_rom_dataspace &_config;
Genode::Signal_context_capability _mode_sigh;
Timer::Connection _timer;
Genode::Ram_allocator &_ram;
Genode::Attached_ram_dataspace _ds;
bool _in_mode_change = true;
public:
Session_component(Genode::Env &env,
Genode::Attached_rom_dataspace &config)
: _driver(env, *this), _config(config), _timer(env),
_ram(env.ram()), _ds(env.ram(), env.rm(), 0) {}
Driver & driver() { return _driver; }
void config_changed()
{
_config.update();
if (!_config.valid()) return;
_in_mode_change = true;
_driver.update_mode();
if (_mode_sigh.valid())
Genode::Signal_transmitter(_mode_sigh).submit();
}
Genode::Xml_node config() { return _config.xml(); }
int force_width_from_config()
{
return _config.xml().attribute_value<unsigned>("force_width", 0);
}
int force_height_from_config()
{
return _config.xml().attribute_value<unsigned>("force_height", 0);
}
/***********************************
** Framebuffer session interface **
***********************************/
Genode::Dataspace_capability dataspace() override
{
_ds.realloc(&_ram, _driver.width() * _driver.height() *
mode().bytes_per_pixel());
_in_mode_change = false;
return _ds.cap();
}
Mode mode() const override {
return Mode { .area = { _driver.width(), _driver.height() } }; }
void mode_sigh(Genode::Signal_context_capability sigh) override {
_mode_sigh = sigh; }
void sync_sigh(Genode::Signal_context_capability sigh) override
{
_timer.sigh(sigh);
_timer.trigger_periodic(10*1000);
}
void refresh(int x, int y, int w, int h) override
{
using namespace Genode;
if (!_driver.fb_addr() || !_ds.local_addr<void>() || _in_mode_change)
return;
int width = _driver.width();
int height = _driver.height();
unsigned bpp = 4;
unsigned pitch = _driver.width();
/* clip specified coordinates against screen boundaries */
int x2 = min(x + w - 1, width - 1),
y2 = min(y + h - 1, height - 1);
int x1 = max(x, 0),
y1 = max(y, 0);
if (x1 > x2 || y1 > y2) return;
/* copy pixels from back buffer to physical frame buffer */
char *src = _ds.local_addr<char>() + bpp*(width*y1 + x1),
*dst = (char*)_driver.fb_addr() + bpp*(pitch*y1 + x1);
blit(src, bpp*width, dst, bpp*pitch,
bpp*(x2 - x1 + 1), y2 - y1 + 1);
}
};
struct Framebuffer::Root
: Genode::Root_component<Framebuffer::Session_component, Genode::Single_client>
{
Session_component session; /* single session */
Session_component *_create_session(const char *) override {
return &session; }
void _destroy_session(Session_component *) override { }
Root(Genode::Env &env, Genode::Allocator &alloc,
Genode::Attached_rom_dataspace &config)
: Genode::Root_component<Session_component,
Genode::Single_client>(env.ep(), alloc),
session(env, config) { }
};
#endif /* __COMPONENT_H__ */