9
0
Fork 0

Merge branch 'for-next/fb'

This commit is contained in:
Sascha Hauer 2015-09-01 09:43:53 +02:00
commit b6b7203aca
9 changed files with 111 additions and 45 deletions

View File

@ -1458,6 +1458,7 @@ endif
config CMD_SPLASH
bool
select IMAGE_RENDERER
depends on VIDEO
prompt "splash"
help
Display a BMP image on a framebuffer device

View File

@ -15,9 +15,9 @@ static int do_splash(int argc, char *argv[])
int opt;
char *fbdev = "/dev/fb0";
char *image_file;
int offscreen = 0;
u32 bg_color = 0x00000000;
bool do_bg = false;
void *buf;
memset(&s, 0, sizeof(s));
@ -41,8 +41,6 @@ static int do_splash(int argc, char *argv[])
case 'y':
s.y = simple_strtoul(optarg, NULL, 0);
break;
case 'o':
offscreen = 1;
}
}
@ -52,21 +50,17 @@ static int do_splash(int argc, char *argv[])
}
image_file = argv[optind];
sc = fb_open(fbdev, offscreen);
sc = fb_open(fbdev);
if (IS_ERR(sc)) {
perror("fd_open");
return PTR_ERR(sc);
}
if (sc->offscreenbuf) {
if (do_bg)
gu_memset_pixel(sc->info, sc->offscreenbuf, bg_color,
sc->s.width * sc->s.height);
else
memcpy(sc->offscreenbuf, sc->fb, sc->fbsize);
} else if (do_bg) {
gu_memset_pixel(sc->info, sc->fb, bg_color, sc->s.width * sc->s.height);
}
buf = gui_screen_render_buffer(sc);
if (do_bg)
gu_memset_pixel(sc->info, buf, bg_color,
sc->s.width * sc->s.height);
ret = image_renderer_file(sc, &s, image_file);
if (ret > 0)
@ -89,7 +83,6 @@ BAREBOX_CMD_HELP_OPT ("-f FB\t", "framebuffer device (default /dev/fb0)")
BAREBOX_CMD_HELP_OPT ("-x XOFFS", "x offset (default center)")
BAREBOX_CMD_HELP_OPT ("-y YOFFS", "y offset (default center)")
BAREBOX_CMD_HELP_OPT ("-b COLOR", "background color in 0xttrrggbb")
BAREBOX_CMD_HELP_OPT ("-o\t", "render offscreen")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(splash)

View File

@ -7,6 +7,7 @@ if VIDEO
config FRAMEBUFFER_CONSOLE
bool
depends on !CONSOLE_NONE
select IMAGE_RENDERER
select FONTS
prompt "framebuffer console support"

View File

@ -11,10 +11,12 @@
static int fb_ioctl(struct cdev* cdev, int req, void *data)
{
struct fb_info *info = cdev->priv;
struct fb_info **fb;
switch (req) {
case FBIOGET_SCREENINFO:
memcpy(data, info, sizeof(*info));
fb = data;
*fb = info;
break;
case FBIO_ENABLE:
info->fbops->fb_enable(info);
@ -29,11 +31,40 @@ static int fb_ioctl(struct cdev* cdev, int req, void *data)
return 0;
}
static int fb_alloc_shadowfb(struct fb_info *info)
{
if (info->screen_base_shadow && info->shadowfb)
return 0;
if (!info->screen_base_shadow && !info->shadowfb)
return 0;
if (info->shadowfb) {
info->screen_base_shadow = memalign(PAGE_SIZE,
info->line_length * info->yres);
if (!info->screen_base_shadow)
return -ENOMEM;
memcpy(info->screen_base_shadow, info->screen_base,
info->line_length * info->yres);
} else {
free(info->screen_base_shadow);
info->screen_base_shadow = NULL;
}
return 0;
}
int fb_enable(struct fb_info *info)
{
int ret;
if (info->enabled)
return 0;
ret = fb_alloc_shadowfb(info);
if (ret)
return ret;
info->fbops->fb_enable(info);
info->enabled = true;
@ -186,6 +217,22 @@ static void fb_info(struct device_d *dev)
fb_print_modes(&info->edid_modes);
}
void *fb_get_screen_base(struct fb_info *info)
{
return info->screen_base_shadow ?
info->screen_base_shadow : info->screen_base;
}
int fb_set_shadowfb(struct param_d *p, void *priv)
{
struct fb_info *info = priv;
if (!info->enabled)
return 0;
return fb_alloc_shadowfb(info);
}
int register_framebuffer(struct fb_info *info)
{
int id = get_free_deviceid("fb");
@ -243,6 +290,8 @@ int register_framebuffer(struct fb_info *info)
for (i = 0; i < info->edid_modes.num_modes; i++)
names[i + info->modes.num_modes] = info->edid_modes.modes[i].name;
dev_add_param_enum(dev, "mode_name", fb_set_modename, NULL, &info->current_mode, names, num_modes, info);
info->shadowfb = 1;
dev_add_param_bool(dev, "shadowfb", fb_set_shadowfb, NULL, &info->shadowfb, info);
info->mode = fb_num_to_mode(info, 0);

View File

@ -40,6 +40,7 @@ struct fbc_priv {
u8 csi[256];
int active;
int in_console;
};
static int fbc_getc(struct console_device *cdev)
@ -57,6 +58,7 @@ static void cls(struct fbc_priv *priv)
void *buf = gui_screen_render_buffer(priv->sc);
memset(buf, 0, priv->fb->line_length * priv->fb->yres);
gu_screen_blit(priv->sc);
}
struct rgb {
@ -137,6 +139,8 @@ static void video_invertchar(struct fbc_priv *priv, int x, int y)
gu_invert_area(priv->fb, buf, x * priv->font_width, y * priv->font_height,
priv->font_width, priv->font_height);
gu_screen_blit_area(priv->sc, x * priv->font_width, y * priv->font_height,
priv->font_width, priv->font_height);
}
static void printchar(struct fbc_priv *priv, int c)
@ -169,7 +173,10 @@ static void printchar(struct fbc_priv *priv, int c)
default:
drawchar(priv, priv->x, priv->y, c);
gu_screen_blit(priv->sc);
gu_screen_blit_area(priv->sc, priv->x * priv->font_width,
priv->y * priv->font_height,
priv->font_width, priv->font_height);
priv->x++;
if (priv->x > priv->cols) {
@ -187,6 +194,7 @@ static void printchar(struct fbc_priv *priv, int c)
memcpy(buf, buf + line_height, line_height * (priv->rows + 1));
memset(buf + line_height * priv->rows, 0, line_height);
gu_screen_blit(priv->sc);
priv->y = priv->rows;
}
@ -250,6 +258,7 @@ static void fbc_parse_csi(struct fbc_priv *priv)
return;
case 'J':
cls(priv);
video_invertchar(priv, priv->x, priv->y);
return;
case 'H':
video_invertchar(priv, priv->x, priv->y);
@ -282,6 +291,10 @@ static void fbc_putc(struct console_device *cdev, char c)
struct fbc_priv *priv = container_of(cdev,
struct fbc_priv, cdev);
if (priv->in_console)
return;
priv->in_console = 1;
switch (priv->state) {
case LIT:
switch (c) {
@ -329,6 +342,7 @@ static void fbc_putc(struct console_device *cdev, char c)
}
break;
}
priv->in_console = 0;
}
static int setup_font(struct fbc_priv *priv)
@ -370,7 +384,7 @@ static int fbc_set_active(struct console_device *cdev, unsigned flags)
if (ret)
return ret;
priv->sc = fb_create_screen(fb, 0);
priv->sc = fb_create_screen(fb);
if (IS_ERR(priv->sc))
return PTR_ERR(priv->sc);

View File

@ -118,6 +118,7 @@ struct fb_info {
struct device_d dev; /* This is this fb device */
void *screen_base;
void *screen_base_shadow;
unsigned long screen_size;
void *priv;
@ -141,6 +142,7 @@ struct fb_info {
int register_simplefb; /* If true a simplefb device node will
* be created.
*/
int shadowfb;
};
struct display_timings *of_get_display_timings(struct device_node *np);
@ -167,5 +169,6 @@ void fb_edid_add_modes(struct fb_info *info);
void fb_of_reserve_add_fixup(struct fb_info *info);
int register_fbconsole(struct fb_info *fb);
void *fb_get_screen_base(struct fb_info *info);
#endif /* __FB_H */

View File

@ -19,11 +19,13 @@ void gu_set_pixel(struct fb_info *info, void *adr, u32 px);
void gu_set_rgb_pixel(struct fb_info *info, void *adr, u8 r, u8 g, u8 b);
void gu_set_rgba_pixel(struct fb_info *info, void *adr, u8 r, u8 g, u8 b, u8 a);
void gu_memset_pixel(struct fb_info *info, void* buf, u32 color, size_t size);
struct screen *fb_create_screen(struct fb_info *info, bool offscreen);
struct screen *fb_open(const char *fbdev, bool offscreen);
struct screen *fb_create_screen(struct fb_info *info);
struct screen *fb_open(const char *fbdev);
void fb_close(struct screen *sc);
void gu_screen_blit(struct screen *sc);
void gu_invert_area(struct fb_info *info, void *buf, int startx, int starty, int width,
int height);
void gu_screen_blit_area(struct screen *sc, int startx, int starty, int width,
int height);
#endif /* __GRAPHIC_UTILS_H__ */

View File

@ -23,16 +23,12 @@ struct screen {
struct surface s;
void *fb;
void *offscreenbuf;
int fbsize;
};
static inline void *gui_screen_render_buffer(struct screen *sc)
{
if (sc->offscreenbuf)
return sc->offscreenbuf;
return sc->fb;
return fb_get_screen_base(sc->info);
}
#endif /* __GUI_H__ */

View File

@ -245,7 +245,7 @@ void gu_rgba_blend(struct fb_info *info, struct image *img, void* buf, int heigh
}
}
struct screen *fb_create_screen(struct fb_info *info, bool offscreen)
struct screen *fb_create_screen(struct fb_info *info)
{
struct screen *sc;
@ -257,19 +257,12 @@ struct screen *fb_create_screen(struct fb_info *info, bool offscreen)
sc->s.height = info->yres;
sc->fbsize = info->line_length * sc->s.height;
sc->fb = info->screen_base;
if (offscreen) {
/*
* Don't fail if malloc fails, just continue rendering directly
* on the framebuffer
*/
sc->offscreenbuf = malloc(sc->fbsize);
}
sc->info = info;
return sc;
}
struct screen *fb_open(const char * fbdev, bool offscreen)
struct screen *fb_open(const char * fbdev)
{
int fd, ret;
struct fb_info *info;
@ -281,12 +274,12 @@ struct screen *fb_open(const char * fbdev, bool offscreen)
info = xzalloc(sizeof(*info));
ret = ioctl(fd, FBIOGET_SCREENINFO, info);
ret = ioctl(fd, FBIOGET_SCREENINFO, &info);
if (ret) {
goto failed_screeninfo;
}
sc = fb_create_screen(info, offscreen);
sc = fb_create_screen(info);
if (IS_ERR(sc)) {
ret = PTR_ERR(sc);
goto failed_create;
@ -298,7 +291,6 @@ struct screen *fb_open(const char * fbdev, bool offscreen)
return sc;
failed_create:
free(sc->offscreenbuf);
free(sc);
failed_screeninfo:
close(fd);
@ -308,20 +300,35 @@ failed_screeninfo:
void fb_close(struct screen *sc)
{
free(sc->offscreenbuf);
if (sc->fd > 0) {
if (sc->fd > 0)
close(sc->fd);
free(sc->info);
}
free(sc);
}
void gu_screen_blit_area(struct screen *sc, int startx, int starty, int width,
int height)
{
struct fb_info *info = sc->info;
int bpp = info->bits_per_pixel >> 3;
if (info->screen_base_shadow) {
int y;
void *fb = info->screen_base + starty * sc->info->line_length + startx * bpp;
void *fboff = info->screen_base_shadow + starty * sc->info->line_length + startx * bpp;
for (y = starty; y < starty + height; y++) {
memcpy(fb, fboff, width * bpp);
fb += sc->info->line_length;
fboff += sc->info->line_length;
}
}
}
void gu_screen_blit(struct screen *sc)
{
if (!sc->offscreenbuf)
return;
struct fb_info *info = sc->info;
memcpy(sc->fb, sc->offscreenbuf, sc->fbsize);
if (info->screen_base_shadow)
memcpy(info->screen_base, info->screen_base_shadow, sc->fbsize);
}