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 <[EMAIL PROTECTED]>

---
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 <[EMAIL PROTECTED]>
+ *
+ *  Code based upon "Bootsplash" (C) 2001-2003 
+ *       Volker Poplawski <[EMAIL PROTECTED]>,
+ *       Stefan Reinauer <[EMAIL PROTECTED]>,
+ *       Steffen Winterfeldt <[EMAIL PROTECTED]>,
+ *       Michael Schroeder <[EMAIL PROTECTED]>,
+ *       Ken Wimer <[EMAIL PROTECTED]>.
+ *
+ *  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 [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to