[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v3 3/8] xen: introduce a generic framebuffer driver
Abstract away from vesa.c the funcions to handle a linear framebuffer and print characters to it. The corresponding functions are going to be removed from vesa.c in the next patch. Changes in v3: - rename fb_cr to fb_carriage_return. Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> --- xen/drivers/video/Makefile | 1 + xen/drivers/video/fb.c | 209 ++++++++++++++++++++++++++++++++++++++++++++ xen/drivers/video/fb.h | 49 ++++++++++ 3 files changed, 259 insertions(+), 0 deletions(-) create mode 100644 xen/drivers/video/fb.c create mode 100644 xen/drivers/video/fb.h diff --git a/xen/drivers/video/Makefile b/xen/drivers/video/Makefile index 2993c39..3b3eb43 100644 --- a/xen/drivers/video/Makefile +++ b/xen/drivers/video/Makefile @@ -2,4 +2,5 @@ obj-$(HAS_VGA) := vga.o obj-$(HAS_VIDEO) += font_8x14.o obj-$(HAS_VIDEO) += font_8x16.o obj-$(HAS_VIDEO) += font_8x8.o +obj-$(HAS_VIDEO) += fb.o obj-$(HAS_VGA) += vesa.o diff --git a/xen/drivers/video/fb.c b/xen/drivers/video/fb.c new file mode 100644 index 0000000..a4f0500 --- /dev/null +++ b/xen/drivers/video/fb.c @@ -0,0 +1,209 @@ +/****************************************************************************** + * fb.c + * + * linear frame buffer handling. + */ + +#include <xen/config.h> +#include <xen/kernel.h> +#include <xen/lib.h> +#include <xen/errno.h> +#include "fb.h" +#include "font.h" + +#define MAX_XRES 1900 +#define MAX_YRES 1200 +#define MAX_BPP 4 +#define MAX_FONT_W 8 +#define MAX_FONT_H 16 +static __initdata unsigned int line_len[MAX_XRES / MAX_FONT_W]; +static __initdata unsigned char lbuf[MAX_XRES * MAX_BPP]; +static __initdata unsigned char text_buf[(MAX_XRES / MAX_FONT_W) * \ + (MAX_YRES / MAX_FONT_H)]; + +struct fb_status { + struct fb_prop fbp; + + unsigned char *lbuf, *text_buf; + unsigned int *line_len; + unsigned int xpos, ypos; +}; +static struct fb_status fb; + +static void fb_show_line( + const unsigned char *text_line, + unsigned char *video_line, + unsigned int nr_chars, + unsigned int nr_cells) +{ + unsigned int i, j, b, bpp, pixel; + + bpp = (fb.fbp.bits_per_pixel + 7) >> 3; + + for ( i = 0; i < fb.fbp.font->height; i++ ) + { + unsigned char *ptr = fb.lbuf; + + for ( j = 0; j < nr_chars; j++ ) + { + const unsigned char *bits = fb.fbp.font->data; + bits += ((text_line[j] * fb.fbp.font->height + i) * + ((fb.fbp.font->width + 7) >> 3)); + for ( b = fb.fbp.font->width; b--; ) + { + pixel = (*bits & (1u<<b)) ? fb.fbp.pixel_on : 0; + memcpy(ptr, &pixel, bpp); + ptr += bpp; + } + } + + memset(ptr, 0, (fb.fbp.width - nr_chars * fb.fbp.font->width) * bpp); + memcpy(video_line, fb.lbuf, nr_cells * fb.fbp.font->width * bpp); + video_line += fb.fbp.bytes_per_line; + } +} + +/* Fast mode which redraws all modified parts of a 2D text buffer. */ +void fb_redraw_puts(const char *s) +{ + unsigned int i, min_redraw_y = fb.ypos; + char c; + + /* Paste characters into text buffer. */ + while ( (c = *s++) != '\0' ) + { + if ( (c == '\n') || (fb.xpos >= fb.fbp.text_columns) ) + { + if ( ++fb.ypos >= fb.fbp.text_rows ) + { + min_redraw_y = 0; + fb.ypos = fb.fbp.text_rows - 1; + memmove(fb.text_buf, fb.text_buf + fb.fbp.text_columns, + fb.ypos * fb.fbp.text_columns); + memset(fb.text_buf + fb.ypos * fb.fbp.text_columns, 0, fb.xpos); + } + fb.xpos = 0; + } + + if ( c != '\n' ) + fb.text_buf[fb.xpos++ + fb.ypos * fb.fbp.text_columns] = c; + } + + /* Render modified section of text buffer to VESA linear framebuffer. */ + for ( i = min_redraw_y; i <= fb.ypos; i++ ) + { + const unsigned char *line = fb.text_buf + i * fb.fbp.text_columns; + unsigned int width; + + for ( width = fb.fbp.text_columns; width; --width ) + if ( line[width - 1] ) + break; + fb_show_line(line, + fb.fbp.lfb + i * fb.fbp.font->height * fb.fbp.bytes_per_line, + width, max(fb.line_len[i], width)); + fb.line_len[i] = width; + } + + fb.fbp.flush(); +} + +/* Slower line-based scroll mode which interacts better with dom0. */ +void fb_scroll_puts(const char *s) +{ + unsigned int i; + char c; + + while ( (c = *s++) != '\0' ) + { + if ( (c == '\n') || (fb.xpos >= fb.fbp.text_columns) ) + { + unsigned int bytes = (fb.fbp.width * + ((fb.fbp.bits_per_pixel + 7) >> 3)); + unsigned char *src = fb.fbp.lfb + fb.fbp.font->height * fb.fbp.bytes_per_line; + unsigned char *dst = fb.fbp.lfb; + + /* New line: scroll all previous rows up one line. */ + for ( i = fb.fbp.font->height; i < fb.fbp.height; i++ ) + { + memcpy(dst, src, bytes); + src += fb.fbp.bytes_per_line; + dst += fb.fbp.bytes_per_line; + } + + /* Render new line. */ + fb_show_line( + fb.text_buf, + fb.fbp.lfb + (fb.fbp.text_rows-1) * fb.fbp.font->height * fb.fbp.bytes_per_line, + fb.xpos, fb.fbp.text_columns); + + fb.xpos = 0; + } + + if ( c != '\n' ) + fb.text_buf[fb.xpos++] = c; + } + + fb.fbp.flush(); +} + +void fb_carriage_return(void) +{ + fb.xpos = 0; +} + +int __init fb_init(struct fb_prop fbp) +{ + if ( fbp.width > MAX_XRES || fbp.height > MAX_YRES ) + { + printk("Couldn't initialize a %xx%x framebuffer early.\n", + fbp.width, fbp.height); + return -EINVAL; + } + + fb.fbp = fbp; + fb.lbuf = lbuf; + fb.text_buf = text_buf; + fb.line_len = line_len; + return 0; +} + +int __init fb_alloc(void) +{ + fb.lbuf = NULL; + fb.text_buf = NULL; + fb.line_len = NULL; + + fb.lbuf = xmalloc_bytes(fb.fbp.bytes_per_line); + if ( !fb.lbuf ) + goto fail; + + fb.text_buf = xzalloc_bytes(fb.fbp.text_columns * fb.fbp.text_rows); + if ( !fb.text_buf ) + goto fail; + + fb.line_len = xzalloc_array(unsigned int, fb.fbp.text_columns); + if ( !fb.line_len ) + goto fail; + + memcpy(fb.lbuf, lbuf, fb.fbp.bytes_per_line); + memcpy(fb.text_buf, text_buf, fb.fbp.text_columns * fb.fbp.text_rows); + memcpy(fb.line_len, line_len, fb.fbp.text_columns); + + return 0; + +fail: + printk(XENLOG_ERR "Couldn't allocate enough memory to drive " + "the framebuffer\n"); + xfree(fb.lbuf); + xfree(fb.text_buf); + xfree(fb.line_len); + + return -ENOMEM; +} + +void fb_free(void) +{ + xfree(fb.lbuf); + xfree(fb.text_buf); + xfree(fb.line_len); +} diff --git a/xen/drivers/video/fb.h b/xen/drivers/video/fb.h new file mode 100644 index 0000000..0084ffa --- /dev/null +++ b/xen/drivers/video/fb.h @@ -0,0 +1,49 @@ +/* + * xen/drivers/video/fb.h + * + * Cross-platform framebuffer library + * + * Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> + * Copyright (c) 2012 Citrix Systems. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _XEN_FB_H +#define _XEN_FB_H + +#include <xen/init.h> + +struct fb_prop { + const struct font_desc *font; + unsigned char *lfb; + unsigned int pixel_on; + uint16_t width, height; + uint16_t bytes_per_line; + uint16_t bits_per_pixel; + void (*flush)(void); + + unsigned int text_columns; + unsigned int text_rows; +}; + +void fb_redraw_puts(const char *s); +void fb_scroll_puts(const char *s); +void fb_carriage_return(void); +void fb_free(void); + +/* initialize the framebuffer, can be called early (before xmalloc is + * available) */ +int __init fb_init(struct fb_prop fbp); +/* fb_alloc allocates internal structures using xmalloc */ +int __init fb_alloc(void); + +#endif -- 1.7.2.5 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |