[announce 2/7] fbsplash - rendering routines

From: Michal Januszewski
Date: Mon Mar 07 2005 - 21:20:05 EST


Fbsplash has its own set of rendering functions. These are
unaccelerated but they should work with different framebuffer drivers.
All rendering routines are completely separate from fbcon.

Signed-off-by: Michael Januszewski <spock@xxxxxxxxxx>

---
diff -Nru a/drivers/video/cfbsplash.c b/drivers/video/cfbsplash.c
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/drivers/video/cfbsplash.c 2005-03-07 16:50:34 +01:00
@@ -0,0 +1,468 @@
+/*
+ * linux/drivers/video/cfbsplash.c -- Framebuffer splash rendering functions
+ *
+ * Copyright (C) 2004-2005 Michael Januszewski <spock@xxxxxxxxxx>
+ *
+ * Code based upon "Bootsplash" (C) 2001-2003
+ * Volker Poplawski <volker@xxxxxxxxxxxx>,
+ * Stefan Reinauer <stepan@xxxxxxx>,
+ * Steffen Winterfeldt <snwint@xxxxxxx>,
+ * Michael Schroeder <mls@xxxxxxx>,
+ * Ken Wimer <wimer@xxxxxxx>.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/fb.h>
+#include <linux/selection.h>
+#include <linux/vt_kern.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include "console/fbcon.h"
+#include "fbsplash.h"
+
+#define parse_pixel(shift,bpp,type) \
+ do { \
+ if (d & (0x80 >> (shift))) \
+ dd2[(shift)] = fgx; \
+ else \
+ dd2[(shift)] = transparent ? *(type *)splash_src : bgx; \
+ splash_src += (bpp); \
+ } while (0) \
+
+extern int get_color(struct vc_data *vc, struct fb_info *info,
+ u16 c, int is_fg);
+
+void fbsplash_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc)
+{
+ int i, j, k;
+ int minlen = min(min(info->var.red.length, info->var.green.length),
+ info->var.blue.length);
+ u32 col;
+
+ for (j = i = 0; i < 16; i++) {
+ k = color_table[i];
+
+ col = ((vc->vc_palette[j++] >> (8-minlen))
+ << info->var.red.offset);
+ col |= ((vc->vc_palette[j++] >> (8-minlen))
+ << info->var.green.offset);
+ col |= ((vc->vc_palette[j++] >> (8-minlen))
+ << info->var.blue.offset);
+ ((u32 *)info->pseudo_palette)[k] = col;
+ }
+}
+
+void fbsplash_renderc(struct fb_info *info, int ypos, int xpos, int height,
+ int width, u8* src, u32 fgx, u32 bgx, u8 transparent)
+{
+ unsigned int x, y;
+ u32 dd;
+ int bytespp = ((info->var.bits_per_pixel + 7) >> 3);
+ unsigned int d = ypos * info->fix.line_length + xpos * bytespp;
+ unsigned int ds = (ypos * info->var.xres + xpos) * bytespp;
+ u16 dd2[4];
+
+ u8* splash_src = (u8 *)(info->splash.data + ds);
+ u8* dst = (u8 *)(info->screen_base + d);
+
+ if ((ypos + height) > info->var.yres || (xpos + width) > info->var.xres)
+ return;
+
+ for (y = 0; y < height; y++) {
+ switch (info->var.bits_per_pixel) {
+
+ case 32:
+ for (x = 0; x < width; x++) {
+
+ if ((x & 7) == 0)
+ d = *src++;
+ if (d & 0x80)
+ dd = fgx;
+ else
+ dd = transparent ?
+ *(u32 *)splash_src : bgx;
+
+ d <<= 1;
+ splash_src += 4;
+ fb_writel(dd, dst);
+ dst += 4;
+ }
+ break;
+ case 24:
+ for (x = 0; x < width; x++) {
+
+ if ((x & 7) == 0)
+ d = *src++;
+ if (d & 0x80)
+ dd = fgx;
+ else
+ dd = transparent ?
+ (*(u32 *)splash_src & 0xffffff) : bgx;
+
+ d <<= 1;
+ splash_src += 3;
+#ifdef __LITTLE_ENDIAN
+ fb_writew(dd & 0xffff, dst);
+ dst += 2;
+ fb_writeb((dd >> 16), dst);
+#else
+ fb_writew(dd >> 8, dst);
+ dst += 2;
+ fb_writeb(dd & 0xff, dst);
+#endif
+ dst++;
+ }
+ break;
+ case 16:
+ for (x = 0; x < width; x += 2) {
+ if ((x & 7) == 0)
+ d = *src++;
+
+ parse_pixel(0, 2, u16);
+ parse_pixel(1, 2, u16);
+#ifdef __LITTLE_ENDIAN
+ dd = dd2[0] | (dd2[1] << 16);
+#else
+ dd = dd2[1] | (dd2[0] << 16);
+#endif
+ d <<= 2;
+ fb_writel(dd, dst);
+ dst += 4;
+ }
+ break;
+
+ case 8:
+ for (x = 0; x < width; x += 4) {
+ if ((x & 7) == 0)
+ d = *src++;
+
+ parse_pixel(0, 1, u8);
+ parse_pixel(1, 1, u8);
+ parse_pixel(2, 1, u8);
+ parse_pixel(3, 1, u8);
+
+#ifdef __LITTLE_ENDIAN
+ dd = dd2[0] | (dd2[1] << 8) | (dd2[2] << 16) | (dd2[3] << 24);
+#else
+ dd = dd2[3] | (dd2[2] << 8) | (dd2[1] << 16) | (dd2[0] << 24);
+#endif
+ d <<= 4;
+ fb_writel(dd, dst);
+ dst += 4;
+ }
+ }
+
+ dst += info->fix.line_length - width * bytespp;
+ splash_src += (info->var.xres - width) * bytespp;
+ }
+}
+
+#define cc2cx(a) \
+ ((info->fix.visual == FB_VISUAL_TRUECOLOR || \
+ info->fix.visual == FB_VISUAL_DIRECTCOLOR) ? \
+ ((u32*)info->pseudo_palette)[a] : a)
+
+void fbsplash_putcs(struct vc_data *vc, struct fb_info *info,
+ const unsigned short *s, int count, int yy, int xx)
+{
+ unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+ int fg_color, bg_color, transparent;
+
+ u8 *src;
+ u32 bgx, fgx;
+
+ u16 c = scr_readw(s);
+
+ fg_color = get_color(vc, info, c, 1);
+ bg_color = get_color(vc, info, c, 0);
+ transparent = vc->vc_splash.bg_color == bg_color;
+
+ xx = xx * vc->vc_font.width + vc->vc_splash.tx;
+ yy = yy * vc->vc_font.height + vc->vc_splash.ty;
+
+ fgx = cc2cx(fg_color);
+ bgx = cc2cx(bg_color);
+
+ while (count--) {
+ c = scr_readw(s++);
+ src = vc->vc_font.data + (c & charmask) * vc->vc_font.height *
+ ((vc->vc_font.width + 7) >> 3);
+
+ fbsplash_renderc(info, yy, xx, vc->vc_font.height,
+ vc->vc_font.width, src, fgx, bgx, transparent);
+ xx += vc->vc_font.width;
+ }
+}
+
+void fbsplash_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+ int i;
+ unsigned int dsize, s_pitch;
+ struct fbcon_ops *ops = info->fbcon_par;
+ struct vc_data* vc;
+ u8 *src;
+
+ /* we really don't need any cursors while the console is blanked */
+ if (info->state != FBINFO_STATE_RUNNING || ops->blank_state)
+ return;
+
+ vc = vc_cons[ops->currcon].d;
+
+ src = kmalloc(64 + sizeof(struct fb_image), GFP_ATOMIC);
+ if (!src)
+ return;
+
+ s_pitch = (cursor->image.width + 7) >> 3;
+ dsize = s_pitch * cursor->image.height;
+ if (cursor->enable) {
+ switch (cursor->rop) {
+ case ROP_XOR:
+ for (i = 0; i < dsize; i++)
+ src[i] = cursor->image.data[i] ^ cursor->mask[i];
+ break;
+ case ROP_COPY:
+ default:
+ for (i = 0; i < dsize; i++)
+ src[i] = cursor->image.data[i] & cursor->mask[i];
+ break;
+ }
+ } else
+ memcpy(src, cursor->image.data, dsize);
+
+ fbsplash_renderc(info,
+ cursor->image.dy + vc->vc_splash.ty,
+ cursor->image.dx + vc->vc_splash.tx,
+ cursor->image.height,
+ cursor->image.width,
+ (u8*)src,
+ cc2cx(cursor->image.fg_color),
+ cc2cx(cursor->image.bg_color),
+ cursor->image.bg_color == vc->vc_splash.bg_color);
+
+ kfree(src);
+}
+
+static void splashset(u8 *dst, int height, int width, int dstbytes,
+ u32 bgx, int bpp)
+{
+ int i;
+
+ if (bpp == 8)
+ bgx |= bgx << 8;
+ if (bpp == 16 || bpp == 8)
+ bgx |= bgx << 16;
+
+ while (height-- > 0) {
+ u8 *p = dst;
+
+ switch (bpp) {
+
+ case 32:
+ for (i=0; i < width; i++) {
+ fb_writel(bgx, p); p += 4;
+ }
+ break;
+ case 24:
+ for (i=0; i < width; i++) {
+#ifdef __LITTLE_ENDIAN
+ fb_writew((bgx & 0xffff),(u16*)p); p += 2;
+ fb_writeb((bgx >> 16),p++);
+#else
+ fb_writew((bgx >> 8),(u16*)p); p += 2;
+ fb_writeb((bgx & 0xff),p++);
+#endif
+ }
+ case 16:
+ for (i=0; i < width/4; i++) {
+ fb_writel(bgx,p); p += 4;
+ fb_writel(bgx,p); p += 4;
+ }
+ if (width & 2) {
+ fb_writel(bgx,p); p += 4;
+ }
+ if (width & 1)
+ fb_writew(bgx,(u16*)p);
+ break;
+ case 8:
+ for (i=0; i < width/4; i++) {
+ fb_writel(bgx,p); p += 4;
+ }
+
+ if (width & 2) {
+ fb_writew(bgx,p); p += 2;
+ }
+ if (width & 1)
+ fb_writeb(bgx,(u8*)p);
+ break;
+
+ }
+ dst += dstbytes;
+ }
+}
+
+void fbsplash_copy(u8 *dst, u8 *src, int height, int width, int linebytes,
+ int srclinebytes, int bpp)
+{
+ int i;
+
+ while (height-- > 0) {
+ u32 *p = (u32 *)dst;
+ u32 *q = (u32 *)src;
+
+ switch (bpp) {
+
+ case 32:
+ for (i=0; i < width; i++)
+ fb_writel(*q++, p++);
+ break;
+ case 24:
+ for (i=0; i < (width*3/4); i++)
+ fb_writel(*q++, p++);
+ if ((width*3) % 4) {
+ if (width & 2) {
+ fb_writeb(*(u8*)q, (u8*)p);
+ } else if (width & 1) {
+ fb_writew(*(u16*)q, (u16*)p);
+ fb_writeb(*(u8*)((u16*)q+1),(u8*)((u16*)p+2));
+ }
+ }
+ break;
+ case 16:
+ for (i=0; i < width/4; i++) {
+ fb_writel(*q++, p++);
+ fb_writel(*q++, p++);
+ }
+ if (width & 2)
+ fb_writel(*q++, p++);
+ if (width & 1)
+ fb_writew(*(u16*)q, (u16*)p);
+ break;
+ case 8:
+ for (i=0; i < width/4; i++)
+ fb_writel(*q++, p++);
+
+ if (width & 2) {
+ fb_writew(*(u16*)q, (u16*)p);
+ q = (u32*) ((u16*)q + 1);
+ p = (u32*) ((u16*)p + 1);
+ }
+ if (width & 1)
+ fb_writeb(*(u8*)q, (u8*)p);
+ break;
+ }
+
+ dst += linebytes;
+ src += srclinebytes;
+ }
+}
+
+static void splashfill(struct fb_info *info, int sy, int sx, int height,
+ int width)
+{
+ int bytespp = ((info->var.bits_per_pixel + 7) >> 3);
+ int d = sy * info->fix.line_length + sx * bytespp;
+ int ds = (sy * info->var.xres + sx) * bytespp;
+
+ fbsplash_copy((u8 *)(info->screen_base + d), (u8 *)(info->splash.data + ds),
+ height, width, info->fix.line_length, info->var.xres * bytespp,
+ info->var.bits_per_pixel);
+}
+
+void fbsplash_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx,
+ int height, int width)
+{
+ int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
+ int bg_color = attr_bgcol_ec(bgshift, vc);
+ int transparent = vc->vc_splash.bg_color == bg_color;
+ u8 *dst;
+
+ sy = sy * vc->vc_font.height + vc->vc_splash.ty;
+ sx = sx * vc->vc_font.width + vc->vc_splash.tx;
+ height *= vc->vc_font.height;
+ width *= vc->vc_font.width;
+
+ if (transparent) {
+ splashfill(info, sy, sx, height, width);
+ } else {
+ dst = (u8 *)(info->screen_base + sy * info->fix.line_length +
+ sx * ((info->var.bits_per_pixel + 7) >> 3));
+ splashset(dst, height, width, info->fix.line_length, cc2cx(bg_color),
+ info->var.bits_per_pixel);
+ }
+}
+
+void fbsplash_clear_margins(struct vc_data *vc, struct fb_info *info,
+ int bottom_only)
+{
+ unsigned int tw = vc->vc_cols*vc->vc_font.width;
+ unsigned int th = vc->vc_rows*vc->vc_font.height;
+
+ if (!bottom_only) {
+ /* top margin */
+ splashfill(info, 0, 0, vc->vc_splash.ty, info->var.xres);
+ /* left margin */
+ splashfill(info, vc->vc_splash.ty, 0, th, vc->vc_splash.tx);
+ /* right margin */
+ splashfill(info, vc->vc_splash.ty, vc->vc_splash.tx + tw, th,
+ info->var.xres - vc->vc_splash.tx - tw);
+ }
+ splashfill(info, vc->vc_splash.ty + th, 0,
+ info->var.yres - vc->vc_splash.ty - th, info->var.xres);
+}
+
+void fbsplash_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y,
+ int sx, int dx, int width)
+{
+ u16 *d = (u16 *) (vc->vc_origin + vc->vc_size_row * y + dx * 2);
+ u16 *s = d + (dx - sx);
+ u16 *start = d;
+ u16 *ls = d;
+ u16 *le = d + width;
+ u16 c;
+ int x = dx;
+ u16 attr = 1;
+
+ do {
+ c = scr_readw(d);
+ if (attr != (c & 0xff00)) {
+ attr = c & 0xff00;
+ if (d > start) {
+ fbsplash_putcs(vc, info, start, d - start, y, x);
+ x += d - start;
+ start = d;
+ }
+ }
+ if (s >= ls && s < le && c == scr_readw(s)) {
+ if (d > start) {
+ fbsplash_putcs(vc, info, start, d - start, y, x);
+ x += d - start + 1;
+ start = d + 1;
+ } else {
+ x++;
+ start++;
+ }
+ }
+ s++;
+ d++;
+ } while (d < le);
+ if (d > start)
+ fbsplash_putcs(vc, info, start, d - start, y, x);
+}
+
+void fbsplash_blank(struct vc_data *vc, struct fb_info *info, int blank)
+{
+ if (blank) {
+ splashset((u8 *)info->screen_base, info->var.yres, info->var.xres,
+ info->fix.line_length, 0, info->var.bits_per_pixel);
+ } else {
+ update_screen(vc->vc_num);
+ fbsplash_clear_margins(vc, info, 0);
+ }
+}
+

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/