Files
genode/repos/dde_linux/src/test/framebuffer/intel/main.cc
Stefan Kalkowski 558cc8e00c intel_fb_drv: make buffering mandatory
Instead of providing a buffer to the client and blitting from that
to the "real" framebuffer as an option, with this commit we always do so.
Thereby its possible to immediately destroy the old framebuffer used by
hardware when a configuration change is done, and a new framebuffer
is used. This also simplifies the modesetting.
Moreover, this commit fixes an issue when not using the connector reporting.
Until now the initial mode detection of connectors was only done when
the report was created. this is a regression that entered the driver
when upgrading to the recent Linux kernel version.

Ref #1997
2016-06-28 11:09:27 +02:00

127 lines
3.1 KiB
C++

/*
* \brief Test controller for Intel framebuffer driver
* \author Stefan Kalkowski
* \date 2016-04-19
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/allocator_avl.h>
#include <base/component.h>
#include <base/heap.h>
#include <base/log.h>
#include <file_system_session/connection.h>
#include <file_system/util.h>
#include <os/attached_rom_dataspace.h>
#include <util/xml_generator.h>
#include <util/xml_node.h>
using namespace Genode;
struct Framebuffer_controller
{
Attached_rom_dataspace rom;
Signal_handler<Framebuffer_controller> rom_sigh;
Heap heap;
Allocator_avl fs_alloc;
File_system::Connection fs;
void update_connector_config(Xml_generator & xml, Xml_node & node);
void update_fb_config(Xml_node & report);
void report_changed();
Framebuffer_controller(Env &env)
: rom("connectors"),
rom_sigh(env.ep(), *this, &Framebuffer_controller::report_changed),
heap(env.ram(), env.rm()),
fs_alloc(&heap),
fs(fs_alloc, 128*1024, "")
{
rom.sigh(rom_sigh);
}
};
void Framebuffer_controller::update_connector_config(Xml_generator & xml,
Xml_node & node)
{
xml.node("connector", [&] {
String<64> name;
node.attribute("name").value(&name);
xml.attribute("name", name.string());
bool connected = node.attribute_value("connected", false);
xml.attribute("enabled", connected ? "true" : "false");
unsigned long width = 0, height = 0;
node.for_each_sub_node("mode", [&] (Xml_node &mode) {
unsigned long w, h;
w = mode.attribute_value<unsigned long>("width", 0);
h = mode.attribute_value<unsigned long>("height", 0);
if (w > width) {
width = w;
height = h;
}
});
if (width && height) {
xml.attribute("width", width);
xml.attribute("height", height);
}
});
}
void Framebuffer_controller::update_fb_config(Xml_node & report)
{
try {
static char buf[4096];
Xml_generator xml(buf, sizeof(buf), "config", [&] {
xml.node("report", [&] {
xml.attribute("connectors", "yes");
});
report.for_each_sub_node("connector", [&] (Xml_node &node) {
update_connector_config(xml, node); });
});
buf[xml.used()] = 0;
File_system::Dir_handle root_dir = fs.dir("/", false);
File_system::File_handle file =
fs.file(root_dir, "fb_drv.config", File_system::READ_WRITE, false);
if (File_system::write(fs, file, buf, xml.used()) == 0)
error("Could not write config");
fs.close(file);
} catch (...) {
error("Cannot update config");
}
}
void Framebuffer_controller::report_changed()
{
rom.update();
if (!rom.is_valid()) return;
Xml_node report(rom.local_addr<char>(), rom.size());
update_fb_config(report);
}
void Component::construct(Genode::Env &env)
{
log("--- Framebuffer controller ---\n");
static Framebuffer_controller controller(env);
}
size_t Component::stack_size() {
return 4*1024*sizeof(long); }