mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-20 14:13:09 +00:00
Double buffering for i.MX53 fb driver (fix #721)
Enable optinal support for double buffering in the i.MX53 framebuffer driver. This prevents flickering in certain scenarios, where applications directly render in the framebuffer dataspace given by the driver.
This commit is contained in:
parent
0950b2f340
commit
cddd69a122
@ -87,8 +87,6 @@ class Framebuffer::Driver
|
||||
return true;
|
||||
}
|
||||
|
||||
Mode mode() { return Mode(_width, _height, Mode::RGB565); }
|
||||
size_t size() { return BYTES_PER_PIXEL * _width * _height; }
|
||||
|
||||
Ipu &ipu() { return _ipu; }
|
||||
Mode mode() { return Mode(_width, _height, Mode::RGB565); }
|
||||
Ipu &ipu() { return _ipu; }
|
||||
};
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* \brief Frame-buffer driver for the i.MX53
|
||||
* \author Nikolay Golikov <nik@ksyslabs.org>
|
||||
* \author Stefan Kalkowski <stefan.kalkowski@genode-labs.com>
|
||||
* \date 2012-06-21
|
||||
*/
|
||||
|
||||
@ -11,6 +12,8 @@
|
||||
#include <base/printf.h>
|
||||
#include <base/sleep.h>
|
||||
#include <os/static_root.h>
|
||||
#include <os/config.h>
|
||||
#include <blit/blit.h>
|
||||
|
||||
/* local includes */
|
||||
#include <driver.h>
|
||||
@ -26,23 +29,34 @@ class Framebuffer::Session_component :
|
||||
{
|
||||
private:
|
||||
|
||||
size_t _size;
|
||||
Dataspace_capability _ds;
|
||||
addr_t _phys_base;
|
||||
Mode _mode;
|
||||
bool _buffered;
|
||||
Mode _mode;
|
||||
size_t _size;
|
||||
|
||||
/* dataspace uses a back buffer (if '_buffered' is true) */
|
||||
Genode::Dataspace_capability _bb_ds;
|
||||
void *_bb_addr;
|
||||
|
||||
/* dataspace of physical frame buffer */
|
||||
Genode::Dataspace_capability _fb_ds;
|
||||
void *_fb_addr;
|
||||
|
||||
Ipu &_ipu;
|
||||
|
||||
public:
|
||||
|
||||
Session_component(Driver &driver)
|
||||
: _size(driver.size()),
|
||||
_ds(env()->ram_session()->alloc(_size, false)),
|
||||
_phys_base(Dataspace_client(_ds).phys_addr()),
|
||||
Session_component(Driver &driver, bool buffered)
|
||||
: _buffered(buffered),
|
||||
_mode(driver.mode()),
|
||||
_size(_mode.bytes_per_pixel() * _mode.width() * _mode.height()),
|
||||
_bb_ds(buffered ? Genode::env()->ram_session()->alloc(_size)
|
||||
: Genode::Ram_dataspace_capability()),
|
||||
_bb_addr(buffered ? (void*)Genode::env()->rm_session()->attach(_bb_ds) : 0),
|
||||
_fb_ds(Genode::env()->ram_session()->alloc(_size, false)),
|
||||
_fb_addr((void*)Genode::env()->rm_session()->attach(_fb_ds)),
|
||||
_ipu(driver.ipu())
|
||||
{
|
||||
if (!driver.init(_phys_base)) {
|
||||
if (!driver.init(Dataspace_client(_fb_ds).phys_addr())) {
|
||||
PERR("Could not initialize display");
|
||||
struct Could_not_initialize_display : Exception { };
|
||||
throw Could_not_initialize_display();
|
||||
@ -54,16 +68,48 @@ class Framebuffer::Session_component :
|
||||
** Framebuffer::session interface **
|
||||
**************************************/
|
||||
|
||||
Dataspace_capability dataspace() { return _ds; }
|
||||
void release() { }
|
||||
Mode mode() const { return _mode; }
|
||||
Dataspace_capability dataspace() { return _buffered ? _bb_ds : _fb_ds; }
|
||||
void release() { }
|
||||
Mode mode() const { return _mode; }
|
||||
void mode_sigh(Genode::Signal_context_capability) { }
|
||||
void refresh(int, int, int, int) { }
|
||||
|
||||
void refresh(int x, int y, int w, int h)
|
||||
{
|
||||
if (!_buffered) return;
|
||||
|
||||
/* clip specified coordinates against screen boundaries */
|
||||
int x2 = min(x + w - 1, (int)_mode.width() - 1),
|
||||
y2 = min(y + h - 1, (int)_mode.height() - 1);
|
||||
int x1 = max(x, 0),
|
||||
y1 = max(y, 0);
|
||||
if (x1 > x2 || y1 > y2) return;
|
||||
|
||||
int bypp = _mode.bytes_per_pixel();
|
||||
|
||||
/* copy pixels from back buffer to physical frame buffer */
|
||||
char *src = (char *)_bb_addr + bypp*(_mode.width()*y + x),
|
||||
*dst = (char *)_fb_addr + bypp*(_mode.width()*y + x);
|
||||
|
||||
blit(src, bypp*_mode.width(), dst, bypp*_mode.width(),
|
||||
bypp*(x2 - x1 + 1), y2 - y1 + 1);
|
||||
}
|
||||
|
||||
void overlay(Genode::addr_t phys_base, int x, int y, int alpha) {
|
||||
_ipu.overlay(phys_base, x, y, alpha); }
|
||||
};
|
||||
|
||||
|
||||
static bool config_attribute(const char *attr_name)
|
||||
{
|
||||
bool result = false;
|
||||
try {
|
||||
result =
|
||||
Genode::config()->xml_node().attribute(attr_name).has_value("yes"); }
|
||||
catch (...) {}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int main(int, char **)
|
||||
{
|
||||
Genode::printf("Starting i.MX53 framebuffer driver\n");
|
||||
@ -76,7 +122,7 @@ int main(int, char **)
|
||||
static Cap_connection cap;
|
||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "fb_ep");
|
||||
|
||||
static Session_component fb_session(driver);
|
||||
static Session_component fb_session(driver, config_attribute("buffered"));
|
||||
static Static_root<Framebuffer::Session> fb_root(ep.manage(&fb_session));
|
||||
|
||||
env()->parent()->announce(ep.manage(&fb_root));
|
||||
|
@ -1,7 +1,7 @@
|
||||
TARGET = fb_drv
|
||||
REQUIRES = imx53
|
||||
SRC_CC = main.cc
|
||||
LIBS = base
|
||||
LIBS = base blit
|
||||
INC_DIR += $(PRG_DIR)
|
||||
|
||||
vpath main.cc $(PRG_DIR)
|
||||
|
Loading…
Reference in New Issue
Block a user