Merge branch 'for-next/fb'
This commit is contained in:
commit
b6b7203aca
|
@ -1458,6 +1458,7 @@ endif
|
||||||
config CMD_SPLASH
|
config CMD_SPLASH
|
||||||
bool
|
bool
|
||||||
select IMAGE_RENDERER
|
select IMAGE_RENDERER
|
||||||
|
depends on VIDEO
|
||||||
prompt "splash"
|
prompt "splash"
|
||||||
help
|
help
|
||||||
Display a BMP image on a framebuffer device
|
Display a BMP image on a framebuffer device
|
||||||
|
|
|
@ -15,9 +15,9 @@ static int do_splash(int argc, char *argv[])
|
||||||
int opt;
|
int opt;
|
||||||
char *fbdev = "/dev/fb0";
|
char *fbdev = "/dev/fb0";
|
||||||
char *image_file;
|
char *image_file;
|
||||||
int offscreen = 0;
|
|
||||||
u32 bg_color = 0x00000000;
|
u32 bg_color = 0x00000000;
|
||||||
bool do_bg = false;
|
bool do_bg = false;
|
||||||
|
void *buf;
|
||||||
|
|
||||||
memset(&s, 0, sizeof(s));
|
memset(&s, 0, sizeof(s));
|
||||||
|
|
||||||
|
@ -41,8 +41,6 @@ static int do_splash(int argc, char *argv[])
|
||||||
case 'y':
|
case 'y':
|
||||||
s.y = simple_strtoul(optarg, NULL, 0);
|
s.y = simple_strtoul(optarg, NULL, 0);
|
||||||
break;
|
break;
|
||||||
case 'o':
|
|
||||||
offscreen = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,21 +50,17 @@ static int do_splash(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
image_file = argv[optind];
|
image_file = argv[optind];
|
||||||
|
|
||||||
sc = fb_open(fbdev, offscreen);
|
sc = fb_open(fbdev);
|
||||||
if (IS_ERR(sc)) {
|
if (IS_ERR(sc)) {
|
||||||
perror("fd_open");
|
perror("fd_open");
|
||||||
return PTR_ERR(sc);
|
return PTR_ERR(sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sc->offscreenbuf) {
|
buf = gui_screen_render_buffer(sc);
|
||||||
if (do_bg)
|
|
||||||
gu_memset_pixel(sc->info, sc->offscreenbuf, bg_color,
|
if (do_bg)
|
||||||
sc->s.width * sc->s.height);
|
gu_memset_pixel(sc->info, buf, bg_color,
|
||||||
else
|
sc->s.width * sc->s.height);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = image_renderer_file(sc, &s, image_file);
|
ret = image_renderer_file(sc, &s, image_file);
|
||||||
if (ret > 0)
|
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 ("-x XOFFS", "x offset (default center)")
|
||||||
BAREBOX_CMD_HELP_OPT ("-y YOFFS", "y 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 ("-b COLOR", "background color in 0xttrrggbb")
|
||||||
BAREBOX_CMD_HELP_OPT ("-o\t", "render offscreen")
|
|
||||||
BAREBOX_CMD_HELP_END
|
BAREBOX_CMD_HELP_END
|
||||||
|
|
||||||
BAREBOX_CMD_START(splash)
|
BAREBOX_CMD_START(splash)
|
||||||
|
|
|
@ -7,6 +7,7 @@ if VIDEO
|
||||||
|
|
||||||
config FRAMEBUFFER_CONSOLE
|
config FRAMEBUFFER_CONSOLE
|
||||||
bool
|
bool
|
||||||
|
depends on !CONSOLE_NONE
|
||||||
select IMAGE_RENDERER
|
select IMAGE_RENDERER
|
||||||
select FONTS
|
select FONTS
|
||||||
prompt "framebuffer console support"
|
prompt "framebuffer console support"
|
||||||
|
|
|
@ -11,10 +11,12 @@
|
||||||
static int fb_ioctl(struct cdev* cdev, int req, void *data)
|
static int fb_ioctl(struct cdev* cdev, int req, void *data)
|
||||||
{
|
{
|
||||||
struct fb_info *info = cdev->priv;
|
struct fb_info *info = cdev->priv;
|
||||||
|
struct fb_info **fb;
|
||||||
|
|
||||||
switch (req) {
|
switch (req) {
|
||||||
case FBIOGET_SCREENINFO:
|
case FBIOGET_SCREENINFO:
|
||||||
memcpy(data, info, sizeof(*info));
|
fb = data;
|
||||||
|
*fb = info;
|
||||||
break;
|
break;
|
||||||
case FBIO_ENABLE:
|
case FBIO_ENABLE:
|
||||||
info->fbops->fb_enable(info);
|
info->fbops->fb_enable(info);
|
||||||
|
@ -29,11 +31,40 @@ static int fb_ioctl(struct cdev* cdev, int req, void *data)
|
||||||
return 0;
|
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 fb_enable(struct fb_info *info)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (info->enabled)
|
if (info->enabled)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
ret = fb_alloc_shadowfb(info);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
info->fbops->fb_enable(info);
|
info->fbops->fb_enable(info);
|
||||||
|
|
||||||
info->enabled = true;
|
info->enabled = true;
|
||||||
|
@ -186,6 +217,22 @@ static void fb_info(struct device_d *dev)
|
||||||
fb_print_modes(&info->edid_modes);
|
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 register_framebuffer(struct fb_info *info)
|
||||||
{
|
{
|
||||||
int id = get_free_deviceid("fb");
|
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++)
|
for (i = 0; i < info->edid_modes.num_modes; i++)
|
||||||
names[i + info->modes.num_modes] = info->edid_modes.modes[i].name;
|
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);
|
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);
|
info->mode = fb_num_to_mode(info, 0);
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ struct fbc_priv {
|
||||||
u8 csi[256];
|
u8 csi[256];
|
||||||
|
|
||||||
int active;
|
int active;
|
||||||
|
int in_console;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int fbc_getc(struct console_device *cdev)
|
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);
|
void *buf = gui_screen_render_buffer(priv->sc);
|
||||||
|
|
||||||
memset(buf, 0, priv->fb->line_length * priv->fb->yres);
|
memset(buf, 0, priv->fb->line_length * priv->fb->yres);
|
||||||
|
gu_screen_blit(priv->sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct rgb {
|
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,
|
gu_invert_area(priv->fb, buf, x * priv->font_width, y * priv->font_height,
|
||||||
priv->font_width, 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)
|
static void printchar(struct fbc_priv *priv, int c)
|
||||||
|
@ -169,7 +173,10 @@ static void printchar(struct fbc_priv *priv, int c)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
drawchar(priv, priv->x, priv->y, c);
|
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++;
|
priv->x++;
|
||||||
if (priv->x > priv->cols) {
|
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));
|
memcpy(buf, buf + line_height, line_height * (priv->rows + 1));
|
||||||
memset(buf + line_height * priv->rows, 0, line_height);
|
memset(buf + line_height * priv->rows, 0, line_height);
|
||||||
|
gu_screen_blit(priv->sc);
|
||||||
priv->y = priv->rows;
|
priv->y = priv->rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,6 +258,7 @@ static void fbc_parse_csi(struct fbc_priv *priv)
|
||||||
return;
|
return;
|
||||||
case 'J':
|
case 'J':
|
||||||
cls(priv);
|
cls(priv);
|
||||||
|
video_invertchar(priv, priv->x, priv->y);
|
||||||
return;
|
return;
|
||||||
case 'H':
|
case 'H':
|
||||||
video_invertchar(priv, priv->x, priv->y);
|
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 *priv = container_of(cdev,
|
||||||
struct fbc_priv, cdev);
|
struct fbc_priv, cdev);
|
||||||
|
|
||||||
|
if (priv->in_console)
|
||||||
|
return;
|
||||||
|
priv->in_console = 1;
|
||||||
|
|
||||||
switch (priv->state) {
|
switch (priv->state) {
|
||||||
case LIT:
|
case LIT:
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
@ -329,6 +342,7 @@ static void fbc_putc(struct console_device *cdev, char c)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
priv->in_console = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int setup_font(struct fbc_priv *priv)
|
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)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
priv->sc = fb_create_screen(fb, 0);
|
priv->sc = fb_create_screen(fb);
|
||||||
if (IS_ERR(priv->sc))
|
if (IS_ERR(priv->sc))
|
||||||
return PTR_ERR(priv->sc);
|
return PTR_ERR(priv->sc);
|
||||||
|
|
||||||
|
|
|
@ -118,6 +118,7 @@ struct fb_info {
|
||||||
struct device_d dev; /* This is this fb device */
|
struct device_d dev; /* This is this fb device */
|
||||||
|
|
||||||
void *screen_base;
|
void *screen_base;
|
||||||
|
void *screen_base_shadow;
|
||||||
unsigned long screen_size;
|
unsigned long screen_size;
|
||||||
|
|
||||||
void *priv;
|
void *priv;
|
||||||
|
@ -141,6 +142,7 @@ struct fb_info {
|
||||||
int register_simplefb; /* If true a simplefb device node will
|
int register_simplefb; /* If true a simplefb device node will
|
||||||
* be created.
|
* be created.
|
||||||
*/
|
*/
|
||||||
|
int shadowfb;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct display_timings *of_get_display_timings(struct device_node *np);
|
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);
|
void fb_of_reserve_add_fixup(struct fb_info *info);
|
||||||
|
|
||||||
int register_fbconsole(struct fb_info *fb);
|
int register_fbconsole(struct fb_info *fb);
|
||||||
|
void *fb_get_screen_base(struct fb_info *info);
|
||||||
|
|
||||||
#endif /* __FB_H */
|
#endif /* __FB_H */
|
||||||
|
|
|
@ -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_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_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);
|
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_create_screen(struct fb_info *info);
|
||||||
struct screen *fb_open(const char *fbdev, bool offscreen);
|
struct screen *fb_open(const char *fbdev);
|
||||||
void fb_close(struct screen *sc);
|
void fb_close(struct screen *sc);
|
||||||
void gu_screen_blit(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,
|
void gu_invert_area(struct fb_info *info, void *buf, int startx, int starty, int width,
|
||||||
int height);
|
int height);
|
||||||
|
void gu_screen_blit_area(struct screen *sc, int startx, int starty, int width,
|
||||||
|
int height);
|
||||||
|
|
||||||
#endif /* __GRAPHIC_UTILS_H__ */
|
#endif /* __GRAPHIC_UTILS_H__ */
|
||||||
|
|
|
@ -23,16 +23,12 @@ struct screen {
|
||||||
struct surface s;
|
struct surface s;
|
||||||
|
|
||||||
void *fb;
|
void *fb;
|
||||||
void *offscreenbuf;
|
|
||||||
int fbsize;
|
int fbsize;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void *gui_screen_render_buffer(struct screen *sc)
|
static inline void *gui_screen_render_buffer(struct screen *sc)
|
||||||
{
|
{
|
||||||
if (sc->offscreenbuf)
|
return fb_get_screen_base(sc->info);
|
||||||
return sc->offscreenbuf;
|
|
||||||
return sc->fb;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* __GUI_H__ */
|
#endif /* __GUI_H__ */
|
||||||
|
|
|
@ -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;
|
struct screen *sc;
|
||||||
|
|
||||||
|
@ -257,19 +257,12 @@ struct screen *fb_create_screen(struct fb_info *info, bool offscreen)
|
||||||
sc->s.height = info->yres;
|
sc->s.height = info->yres;
|
||||||
sc->fbsize = info->line_length * sc->s.height;
|
sc->fbsize = info->line_length * sc->s.height;
|
||||||
sc->fb = info->screen_base;
|
sc->fb = info->screen_base;
|
||||||
|
sc->info = info;
|
||||||
if (offscreen) {
|
|
||||||
/*
|
|
||||||
* Don't fail if malloc fails, just continue rendering directly
|
|
||||||
* on the framebuffer
|
|
||||||
*/
|
|
||||||
sc->offscreenbuf = malloc(sc->fbsize);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sc;
|
return sc;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct screen *fb_open(const char * fbdev, bool offscreen)
|
struct screen *fb_open(const char * fbdev)
|
||||||
{
|
{
|
||||||
int fd, ret;
|
int fd, ret;
|
||||||
struct fb_info *info;
|
struct fb_info *info;
|
||||||
|
@ -281,12 +274,12 @@ struct screen *fb_open(const char * fbdev, bool offscreen)
|
||||||
|
|
||||||
info = xzalloc(sizeof(*info));
|
info = xzalloc(sizeof(*info));
|
||||||
|
|
||||||
ret = ioctl(fd, FBIOGET_SCREENINFO, info);
|
ret = ioctl(fd, FBIOGET_SCREENINFO, &info);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
goto failed_screeninfo;
|
goto failed_screeninfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
sc = fb_create_screen(info, offscreen);
|
sc = fb_create_screen(info);
|
||||||
if (IS_ERR(sc)) {
|
if (IS_ERR(sc)) {
|
||||||
ret = PTR_ERR(sc);
|
ret = PTR_ERR(sc);
|
||||||
goto failed_create;
|
goto failed_create;
|
||||||
|
@ -298,7 +291,6 @@ struct screen *fb_open(const char * fbdev, bool offscreen)
|
||||||
return sc;
|
return sc;
|
||||||
|
|
||||||
failed_create:
|
failed_create:
|
||||||
free(sc->offscreenbuf);
|
|
||||||
free(sc);
|
free(sc);
|
||||||
failed_screeninfo:
|
failed_screeninfo:
|
||||||
close(fd);
|
close(fd);
|
||||||
|
@ -308,20 +300,35 @@ failed_screeninfo:
|
||||||
|
|
||||||
void fb_close(struct screen *sc)
|
void fb_close(struct screen *sc)
|
||||||
{
|
{
|
||||||
free(sc->offscreenbuf);
|
if (sc->fd > 0)
|
||||||
|
|
||||||
if (sc->fd > 0) {
|
|
||||||
close(sc->fd);
|
close(sc->fd);
|
||||||
free(sc->info);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(sc);
|
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)
|
void gu_screen_blit(struct screen *sc)
|
||||||
{
|
{
|
||||||
if (!sc->offscreenbuf)
|
struct fb_info *info = sc->info;
|
||||||
return;
|
|
||||||
|
|
||||||
memcpy(sc->fb, sc->offscreenbuf, sc->fbsize);
|
if (info->screen_base_shadow)
|
||||||
|
memcpy(info->screen_base, info->screen_base_shadow, sc->fbsize);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue