9
0
Fork 0

gui: introduce screen and surface to factorize and simplify code

Instead of passing hundreds of parameter, just pass the right structure.

struct screen represent the screen with a without double buffering.
struct surface represent the part of the screen we want to render.

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
Jean-Christophe PLAGNIOL-VILLARD 2012-09-26 11:59:02 +02:00 committed by Sascha Hauer
parent 21a8ef55b0
commit 3fa8d74abe
7 changed files with 113 additions and 72 deletions

View File

@ -12,17 +12,20 @@
static int do_splash(int argc, char *argv[])
{
struct surface s;
struct screen sc;
int ret, opt, fd;
char *fbdev = "/dev/fb0";
void *fb;
struct fb_info info;
char *image_file;
int startx = -1, starty = -1;
int xres, yres;
int offscreen = 0;
u32 bg_color = 0x00000000;
bool do_bg = false;
void *offscreenbuf = NULL;
s.x = -1;
s.y = -1;
s.width = -1;
s.height = -1;
while((opt = getopt(argc, argv, "f:x:y:ob:")) > 0) {
switch(opt) {
@ -34,10 +37,10 @@ static int do_splash(int argc, char *argv[])
do_bg = true;
break;
case 'x':
startx = simple_strtoul(optarg, NULL, 0);
s.x = simple_strtoul(optarg, NULL, 0);
break;
case 'y':
starty = simple_strtoul(optarg, NULL, 0);
s.y = simple_strtoul(optarg, NULL, 0);
case 'o':
offscreen = 1;
}
@ -55,8 +58,8 @@ static int do_splash(int argc, char *argv[])
return 1;
}
fb = memmap(fd, PROT_READ | PROT_WRITE);
if (fb == (void *)-1) {
sc.fb = memmap(fd, PROT_READ | PROT_WRITE);
if (sc.fb == (void *)-1) {
perror("memmap");
goto failed_memmap;
}
@ -67,33 +70,30 @@ static int do_splash(int argc, char *argv[])
goto failed_memmap;
}
xres = info.xres;
yres = info.yres;
if (offscreen) {
int fbsize;
/* Don't fail if malloc fails, just continue rendering directly
* on the framebuffer
*/
fbsize = xres * yres * (info.bits_per_pixel >> 3);
offscreenbuf = malloc(fbsize);
if (offscreenbuf) {
fbsize = sc.s.x * sc.s.x * (sc.info.bits_per_pixel >> 3);
sc.offscreenbuf = malloc(fbsize);
if (sc.offscreenbuf) {
if (do_bg)
memset_pixel(&info, offscreenbuf, bg_color, xres * yres);
memset_pixel(&info, sc.offscreenbuf, bg_color,
sc.s.width * sc.s.height);
else
memcpy(offscreenbuf, fb, fbsize);
memcpy(sc.offscreenbuf, sc.fb, fbsize);
}
} else if (do_bg) {
memset_pixel(&info, fb, bg_color, xres * yres);
memset_pixel(&info, sc.fb, bg_color, sc.s.width * sc.s.height);
}
if (image_renderer_file(&info, image_file, fb, startx, starty,
offscreenbuf) < 0)
if (image_renderer_file(&sc, &s, image_file) < 0)
ret = 1;
if (offscreenbuf)
free(offscreenbuf);
if (sc.offscreenbuf)
free(sc.offscreenbuf);
close(fd);

View File

@ -9,6 +9,7 @@
#include <fb.h>
#include <gui/image.h>
#include <gui/gui.h>
void rgba_blend(struct fb_info *info, struct image *img, void* dest, int height,
int width, int startx, int starty, bool is_rgba);
@ -16,5 +17,6 @@ void set_pixel(struct fb_info *info, void *adr, u32 px);
void set_rgb_pixel(struct fb_info *info, void *adr, u8 r, u8 g, u8 b);
void set_rgba_pixel(struct fb_info *info, void *adr, u8 r, u8 g, u8 b, u8 a);
void memset_pixel(struct fb_info *info, void* buf, u32 color, size_t size);
int fb_open(const char * fbdev, struct screen *sc);
#endif /* __GRAPHIC_UTILS_H__ */

36
include/gui/gui.h Normal file
View File

@ -0,0 +1,36 @@
/*
* Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
*
* GPL v2
*/
#ifndef __GUI_H__
#define __GUI_H__
#include <fb.h>
struct surface {
int x;
int y;
int width;
int height;
};
struct screen {
struct fb_info info;
struct surface s;
void *fb;
void *offscreenbuf;
};
static inline void* gui_screen_redering_buffer(struct screen *sc)
{
if (sc->offscreenbuf)
return sc->offscreenbuf;
return sc->fb;
}
#endif /* __GUI_H__ */

View File

@ -13,13 +13,13 @@
#include <linux/err.h>
#include <fb.h>
#include <gui/image.h>
#include <gui/gui.h>
struct image_renderer {
enum filetype type;
struct image *(*open)(char *data, int size);
void (*close)(struct image *img);
int (*renderer)(struct fb_info *info, struct image *img, void* fb,
int startx, int starty, void* offscreenbuf);
int (*renderer)(struct screen *sc, struct surface *s, struct image *img);
/*
* do not free the data read from the file
@ -34,8 +34,7 @@ struct image_renderer {
int image_renderer_register(struct image_renderer *ir);
void image_render_unregister(struct image_renderer *ir);
int image_renderer_image(struct fb_info *info, struct image *img, void* fb,
int startx, int starty, void* offscreenbuf);
int image_renderer_image(struct screen *sc, struct surface *s, struct image *img);
struct image *image_renderer_open(const char* file);
void image_renderer_close(struct image *img);
@ -54,12 +53,10 @@ static inline struct image *image_renderer_open(const char* file)
static inline void image_renderer_close(struct image *img) {}
int image_renderer_image(struct fb_info *info, struct image *img, void* fb,
int startx, int starty, void* offscreenbuf);
int image_renderer_image(struct surface *s, struct image *img);
#endif
static inline int image_renderer_file(struct fb_info *info, const char* file, void* fb,
int startx, int starty, void* offscreenbuf)
static inline int image_renderer_file(struct screen *sc, struct surface *s, const char* file)
{
struct image* img = image_renderer_open(file);
int ret;
@ -67,8 +64,7 @@ static inline int image_renderer_file(struct fb_info *info, const char* file, vo
if (IS_ERR(img))
return PTR_ERR(img);
ret = image_renderer_image(info, img, fb, startx, starty,
offscreenbuf);
ret = image_renderer_image(sc, s, img);
image_renderer_close(img);

View File

@ -34,38 +34,42 @@ void bmp_close(struct image *img)
free(img->data);
}
static int bmp_renderer(struct fb_info *info, struct image *img, void* fb,
int startx, int starty, void* offscreenbuf)
static int bmp_renderer(struct screen *sc, struct surface *s, struct image *img)
{
struct bmp_image *bmp = img->data;
int width, height;
int bits_per_pixel, fbsize;
void *adr, *buf;
char *image;
int xres, yres;
int width = s->width;
int height = s->height;
int startx = s->x;
int starty = s->y;
xres = info->xres;
yres = info->yres;
if (s->width < 0)
width = img->width;
if (s->height < 0)
height = img->height;
if (startx < 0) {
startx = (xres - img->width) / 2;
startx = (sc->s.width - width) / 2;
if (startx < 0)
startx = 0;
}
if (starty < 0) {
starty = (yres - img->height) / 2;
starty = (sc->s.height - height) / 2;
if (starty < 0)
starty = 0;
}
width = min(img->width, xres - startx);
height = min(img->height, yres - starty);
width = min(width, sc->s.width - startx);
height = min(height, sc->s.height - starty);
buf = gui_screen_redering_buffer(sc);
bits_per_pixel = img->bits_per_pixel;
fbsize = xres * yres * (info->bits_per_pixel >> 3);
buf = offscreenbuf ? offscreenbuf : fb;
fbsize = sc->s.width * sc->s.height * (sc->info.bits_per_pixel >> 3);
if (bits_per_pixel == 8) {
int x, y;
@ -75,17 +79,17 @@ static int bmp_renderer(struct fb_info *info, struct image *img, void* fb,
image = (char *)bmp +
le32_to_cpu(bmp->header.data_offset);
image += (img->height - y - 1) * img->width * (bits_per_pixel >> 3);
adr = buf + ((y + starty) * xres + startx) *
(info->bits_per_pixel >> 3);
adr = buf + ((y + starty) * sc->s.width + startx) *
(sc->info.bits_per_pixel >> 3);
for (x = 0; x < width; x++) {
int pixel;
pixel = *image;
set_rgb_pixel(info, adr, color_table[pixel].red,
set_rgb_pixel(&sc->info, adr, color_table[pixel].red,
color_table[pixel].green,
color_table[pixel].blue);
adr += info->bits_per_pixel >> 3;
adr += sc->info.bits_per_pixel >> 3;
image += bits_per_pixel >> 3;
}
@ -97,16 +101,16 @@ static int bmp_renderer(struct fb_info *info, struct image *img, void* fb,
image = (char *)bmp +
le32_to_cpu(bmp->header.data_offset);
image += (img->height - y - 1) * img->width * (bits_per_pixel >> 3);
adr = buf + ((y + starty) * xres + startx) *
(info->bits_per_pixel >> 3);
adr = buf + ((y + starty) * sc->s.width + startx) *
(sc->info.bits_per_pixel >> 3);
for (x = 0; x < width; x++) {
char *pixel;
pixel = image;
set_rgb_pixel(info, adr, pixel[2], pixel[1],
set_rgb_pixel(&sc->info, adr, pixel[2], pixel[1],
pixel[0]);
adr += info->bits_per_pixel >> 3;
adr += sc->info.bits_per_pixel >> 3;
image += bits_per_pixel >> 3;
}
@ -114,8 +118,8 @@ static int bmp_renderer(struct fb_info *info, struct image *img, void* fb,
} else
printf("bmp: illegal bits per pixel value: %d\n", bits_per_pixel);
if (offscreenbuf)
memcpy(fb, offscreenbuf, fbsize);
if (sc->offscreenbuf)
memcpy(sc->fb, sc->offscreenbuf, fbsize);
return img->height;
}

View File

@ -71,10 +71,9 @@ void image_renderer_close(struct image *img)
free(img);
}
int image_renderer_image(struct fb_info *info, struct image *img, void* fb,
int startx, int starty, void* offscreenbuf)
int image_renderer_image(struct screen *sc, struct surface *s, struct image *img)
{
return img->ir->renderer(info, img, fb, startx, starty, offscreenbuf);
return img->ir->renderer(sc, s, img);
}
int image_renderer_register(struct image_renderer *ir)

View File

@ -36,40 +36,44 @@ void png_uncompress_exit(void)
}
}
static int png_renderer(struct fb_info *info, struct image *img, void* fb,
int startx, int starty, void* offscreenbuf)
static int png_renderer(struct screen *sc, struct surface *s, struct image *img)
{
int width, height;
void *buf;
int xres, yres;
int width = s->width;
int height = s->height;
int startx = s->x;
int starty = s->y;
xres = info->xres;
yres = info->yres;
if (s->width < 0)
width = img->width;
if (s->height < 0)
height = img->height;
if (startx < 0) {
startx = (xres - img->width) / 2;
startx = (sc->s.width - width) / 2;
if (startx < 0)
startx = 0;
}
if (starty < 0) {
starty = (yres - img->height) / 2;
starty = (sc->s.height - height) / 2;
if (starty < 0)
starty = 0;
}
width = min(img->width, xres - startx);
height = min(img->height, yres - starty);
width = min(width, sc->s.width - startx);
height = min(height, sc->s.height - starty);
buf = offscreenbuf ? offscreenbuf : fb;
buf = gui_screen_redering_buffer(sc);
rgba_blend(info, img, buf, height, width, startx, starty, true);
rgba_blend(&sc->info, img, buf, height, width, startx, starty, true);
if (offscreenbuf) {
if (sc->offscreenbuf) {
int fbsize;
fbsize = xres * yres * (info->bits_per_pixel >> 3);
memcpy(fb, offscreenbuf, fbsize);
fbsize = sc->s.width * sc->s.height * (sc->info.bits_per_pixel >> 3);
memcpy(sc->fb, sc->offscreenbuf, fbsize);
}
return img->height;