Skip to content

Commit

Permalink
[PATCH] fbcon: Console Rotation - Add support to rotate the logo
Browse files Browse the repository at this point in the history
Add support for rotating and positioning of the logo.  Rotation and position
depends on 'int rotate' parameter added to fb_prepare_logo() and
fb_show_logo().

Signed-off-by: Antonino Daplas <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Antonino A. Daplas authored and Linus Torvalds committed Nov 9, 2005
1 parent e4fc276 commit 9c44e5f
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 17 deletions.
5 changes: 3 additions & 2 deletions drivers/video/console/fbcon.c
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
int cols, int rows, int new_cols, int new_rows)
{
/* Need to make room for the logo */
struct fbcon_ops *ops = info->fbcon_par;
int cnt, erase = vc->vc_video_erase_char, step;
unsigned short *save = NULL, *r, *q;

Expand All @@ -508,7 +509,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
*/
if (fb_get_color_depth(&info->var, &info->fix) == 1)
erase &= ~0x400;
logo_height = fb_prepare_logo(info);
logo_height = fb_prepare_logo(info, ops->rotate);
logo_lines = (logo_height + vc->vc_font.height - 1) /
vc->vc_font.height;
q = (unsigned short *) (vc->vc_origin +
Expand Down Expand Up @@ -2073,7 +2074,7 @@ static int fbcon_switch(struct vc_data *vc)

logo_shown = fg_console;
/* This is protected above by initmem_freed */
fb_show_logo(info);
fb_show_logo(info, ops->rotate);
update_region(vc,
vc->vc_origin + vc->vc_size_row * vc->vc_top,
vc->vc_size_row * (vc->vc_bottom -
Expand Down
130 changes: 117 additions & 13 deletions drivers/video/fbmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,9 +323,103 @@ static struct logo_data {
const struct linux_logo *logo;
} fb_logo;

int fb_prepare_logo(struct fb_info *info)
static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height)
{
u32 size = width * height, i;

out += size - 1;

for (i = size; i--; )
*out-- = *in++;
}

static void fb_rotate_logo_cw(const u8 *in, u8 *out, u32 width, u32 height)
{
int i, j, w = width - 1;

for (i = 0; i < height; i++)
for (j = 0; j < width; j++)
out[height * j + w - i] = *in++;
}

static void fb_rotate_logo_ccw(const u8 *in, u8 *out, u32 width, u32 height)
{
int i, j, w = width - 1;

for (i = 0; i < height; i++)
for (j = 0; j < width; j++)
out[height * (w - j) + i] = *in++;
}

static void fb_rotate_logo(struct fb_info *info, u8 *dst,
struct fb_image *image, int rotate)
{
u32 tmp;

if (rotate == FB_ROTATE_UD) {
image->dx = info->var.xres - image->width;
image->dy = info->var.yres - image->height;
fb_rotate_logo_ud(image->data, dst, image->width,
image->height);
} else if (rotate == FB_ROTATE_CW) {
tmp = image->width;
image->width = image->height;
image->height = tmp;
image->dx = info->var.xres - image->height;
fb_rotate_logo_cw(image->data, dst, image->width,
image->height);
} else if (rotate == FB_ROTATE_CCW) {
tmp = image->width;
image->width = image->height;
image->height = tmp;
image->dy = info->var.yres - image->width;
fb_rotate_logo_ccw(image->data, dst, image->width,
image->height);
}

image->data = dst;
}

static void fb_do_show_logo(struct fb_info *info, struct fb_image *image,
int rotate)
{
int x;

if (rotate == FB_ROTATE_UR) {
for (x = 0; x < num_online_cpus() &&
x * (fb_logo.logo->width + 8) <=
info->var.xres - fb_logo.logo->width; x++) {
info->fbops->fb_imageblit(info, image);
image->dx += fb_logo.logo->width + 8;
}
} else if (rotate == FB_ROTATE_UD) {
for (x = 0; x < num_online_cpus() &&
x * (fb_logo.logo->width + 8) <=
info->var.xres - fb_logo.logo->width; x++) {
info->fbops->fb_imageblit(info, image);
image->dx -= fb_logo.logo->width + 8;
}
} else if (rotate == FB_ROTATE_CW) {
for (x = 0; x < num_online_cpus() &&
x * (fb_logo.logo->width + 8) <=
info->var.yres - fb_logo.logo->width; x++) {
info->fbops->fb_imageblit(info, image);
image->dy += fb_logo.logo->width + 8;
}
} else if (rotate == FB_ROTATE_CCW) {
for (x = 0; x < num_online_cpus() &&
x * (fb_logo.logo->width + 8) <=
info->var.yres - fb_logo.logo->width; x++) {
info->fbops->fb_imageblit(info, image);
image->dy -= fb_logo.logo->width + 8;
}
}
}

int fb_prepare_logo(struct fb_info *info, int rotate)
{
int depth = fb_get_color_depth(&info->var, &info->fix);
int yres;

memset(&fb_logo, 0, sizeof(struct logo_data));

Expand Down Expand Up @@ -358,10 +452,16 @@ int fb_prepare_logo(struct fb_info *info)
/* Return if no suitable logo was found */
fb_logo.logo = fb_find_logo(depth);

if (!fb_logo.logo || fb_logo.logo->height > info->var.yres) {
if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD)
yres = info->var.yres;
else
yres = info->var.xres;

if (fb_logo.logo && fb_logo.logo->height > yres) {
fb_logo.logo = NULL;
return 0;
}

/* What depth we asked for might be different from what we get */
if (fb_logo.logo->type == LINUX_LOGO_CLUT224)
fb_logo.depth = 8;
Expand All @@ -372,12 +472,11 @@ int fb_prepare_logo(struct fb_info *info)
return fb_logo.logo->height;
}

int fb_show_logo(struct fb_info *info)
int fb_show_logo(struct fb_info *info, int rotate)
{
u32 *palette = NULL, *saved_pseudo_palette = NULL;
unsigned char *logo_new = NULL;
unsigned char *logo_new = NULL, *logo_rotate = NULL;
struct fb_image image;
int x;

/* Return if the frame buffer is not mapped or suspended */
if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING)
Expand Down Expand Up @@ -417,25 +516,30 @@ int fb_show_logo(struct fb_info *info)
fb_set_logo(info, fb_logo.logo, logo_new, fb_logo.depth);
}

image.dx = 0;
image.dy = 0;
image.width = fb_logo.logo->width;
image.height = fb_logo.logo->height;
image.dy = 0;

for (x = 0; x < num_online_cpus() * (fb_logo.logo->width + 8) &&
x <= info->var.xres-fb_logo.logo->width; x += (fb_logo.logo->width + 8)) {
image.dx = x;
info->fbops->fb_imageblit(info, &image);
if (rotate) {
logo_rotate = kmalloc(fb_logo.logo->width *
fb_logo.logo->height, GFP_KERNEL);
if (logo_rotate)
fb_rotate_logo(info, logo_rotate, &image, rotate);
}


fb_do_show_logo(info, &image, rotate);

kfree(palette);
if (saved_pseudo_palette != NULL)
info->pseudo_palette = saved_pseudo_palette;
kfree(logo_new);
kfree(logo_rotate);
return fb_logo.logo->height;
}
#else
int fb_prepare_logo(struct fb_info *info) { return 0; }
int fb_show_logo(struct fb_info *info) { return 0; }
int fb_prepare_logo(struct fb_info *info, int rotate) { return 0; }
int fb_show_logo(struct fb_info *info, int rotate) { return 0; }
#endif /* CONFIG_LOGO */

static int fbmem_read_proc(char *buf, char **start, off_t offset,
Expand Down
4 changes: 2 additions & 2 deletions include/linux/fb.h
Original file line number Diff line number Diff line change
Expand Up @@ -825,8 +825,8 @@ extern void cfb_imageblit(struct fb_info *info, const struct fb_image *image);
/* drivers/video/fbmem.c */
extern int register_framebuffer(struct fb_info *fb_info);
extern int unregister_framebuffer(struct fb_info *fb_info);
extern int fb_prepare_logo(struct fb_info *fb_info);
extern int fb_show_logo(struct fb_info *fb_info);
extern int fb_prepare_logo(struct fb_info *fb_info, int rotate);
extern int fb_show_logo(struct fb_info *fb_info, int rotate);
extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size);
extern void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx,
u32 height, u32 shift_high, u32 shift_low, u32 mod);
Expand Down

0 comments on commit 9c44e5f

Please sign in to comment.