Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.22-rc7 291 lines 6.9 kB view raw
1/* 2 * Generic 1-bit or 8-bit source to 1-32 bit destination expansion 3 * for frame buffer located in system RAM with packed pixels of any depth. 4 * 5 * Based almost entirely on cfbimgblt.c 6 * 7 * Copyright (C) April 2007 Antonino Daplas <adaplas@pol.net> 8 * 9 * This file is subject to the terms and conditions of the GNU General Public 10 * License. See the file COPYING in the main directory of this archive for 11 * more details. 12 */ 13#include <linux/module.h> 14#include <linux/string.h> 15#include <linux/fb.h> 16#include <asm/types.h> 17 18#define DEBUG 19 20#ifdef DEBUG 21#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt,__FUNCTION__,## args) 22#else 23#define DPRINTK(fmt, args...) 24#endif 25 26static const u32 cfb_tab8[] = { 27#if defined(__BIG_ENDIAN) 28 0x00000000,0x000000ff,0x0000ff00,0x0000ffff, 29 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff, 30 0xff000000,0xff0000ff,0xff00ff00,0xff00ffff, 31 0xffff0000,0xffff00ff,0xffffff00,0xffffffff 32#elif defined(__LITTLE_ENDIAN) 33 0x00000000,0xff000000,0x00ff0000,0xffff0000, 34 0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00, 35 0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff, 36 0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff 37#else 38#error FIXME: No endianness?? 39#endif 40}; 41 42static const u32 cfb_tab16[] = { 43#if defined(__BIG_ENDIAN) 44 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff 45#elif defined(__LITTLE_ENDIAN) 46 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff 47#else 48#error FIXME: No endianness?? 49#endif 50}; 51 52static const u32 cfb_tab32[] = { 53 0x00000000, 0xffffffff 54}; 55 56static void color_imageblit(const struct fb_image *image, struct fb_info *p, 57 void *dst1, u32 start_index, u32 pitch_index) 58{ 59 /* Draw the penguin */ 60 u32 *dst, *dst2; 61 u32 color = 0, val, shift; 62 int i, n, bpp = p->var.bits_per_pixel; 63 u32 null_bits = 32 - bpp; 64 u32 *palette = (u32 *) p->pseudo_palette; 65 const u8 *src = image->data; 66 67 dst2 = dst1; 68 for (i = image->height; i--; ) { 69 n = image->width; 70 dst = dst1; 71 shift = 0; 72 val = 0; 73 74 if (start_index) { 75 u32 start_mask = ~(FB_SHIFT_HIGH(~(u32)0, 76 start_index)); 77 val = *dst & start_mask; 78 shift = start_index; 79 } 80 while (n--) { 81 if (p->fix.visual == FB_VISUAL_TRUECOLOR || 82 p->fix.visual == FB_VISUAL_DIRECTCOLOR ) 83 color = palette[*src]; 84 else 85 color = *src; 86 color <<= FB_LEFT_POS(bpp); 87 val |= FB_SHIFT_HIGH(color, shift); 88 if (shift >= null_bits) { 89 *dst++ = val; 90 91 val = (shift == null_bits) ? 0 : 92 FB_SHIFT_LOW(color, 32 - shift); 93 } 94 shift += bpp; 95 shift &= (32 - 1); 96 src++; 97 } 98 if (shift) { 99 u32 end_mask = FB_SHIFT_HIGH(~(u32)0, shift); 100 101 *dst &= end_mask; 102 *dst |= val; 103 } 104 dst1 += p->fix.line_length; 105 if (pitch_index) { 106 dst2 += p->fix.line_length; 107 dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1)); 108 109 start_index += pitch_index; 110 start_index &= 32 - 1; 111 } 112 } 113} 114 115static void slow_imageblit(const struct fb_image *image, struct fb_info *p, 116 void *dst1, u32 fgcolor, u32 bgcolor, 117 u32 start_index, u32 pitch_index) 118{ 119 u32 shift, color = 0, bpp = p->var.bits_per_pixel; 120 u32 *dst, *dst2; 121 u32 val, pitch = p->fix.line_length; 122 u32 null_bits = 32 - bpp; 123 u32 spitch = (image->width+7)/8; 124 const u8 *src = image->data, *s; 125 u32 i, j, l; 126 127 dst2 = dst1; 128 fgcolor <<= FB_LEFT_POS(bpp); 129 bgcolor <<= FB_LEFT_POS(bpp); 130 131 for (i = image->height; i--; ) { 132 shift = val = 0; 133 l = 8; 134 j = image->width; 135 dst = dst1; 136 s = src; 137 138 /* write leading bits */ 139 if (start_index) { 140 u32 start_mask = ~(FB_SHIFT_HIGH(~(u32)0,start_index)); 141 val = *dst & start_mask; 142 shift = start_index; 143 } 144 145 while (j--) { 146 l--; 147 color = (*s & (1 << l)) ? fgcolor : bgcolor; 148 val |= FB_SHIFT_HIGH(color, shift); 149 150 /* Did the bitshift spill bits to the next long? */ 151 if (shift >= null_bits) { 152 *dst++ = val; 153 val = (shift == null_bits) ? 0 : 154 FB_SHIFT_LOW(color,32 - shift); 155 } 156 shift += bpp; 157 shift &= (32 - 1); 158 if (!l) { l = 8; s++; }; 159 } 160 161 /* write trailing bits */ 162 if (shift) { 163 u32 end_mask = FB_SHIFT_HIGH(~(u32)0, shift); 164 165 *dst &= end_mask; 166 *dst |= val; 167 } 168 169 dst1 += pitch; 170 src += spitch; 171 if (pitch_index) { 172 dst2 += pitch; 173 dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1)); 174 start_index += pitch_index; 175 start_index &= 32 - 1; 176 } 177 178 } 179} 180 181/* 182 * fast_imageblit - optimized monochrome color expansion 183 * 184 * Only if: bits_per_pixel == 8, 16, or 32 185 * image->width is divisible by pixel/dword (ppw); 186 * fix->line_legth is divisible by 4; 187 * beginning and end of a scanline is dword aligned 188 */ 189static void fast_imageblit(const struct fb_image *image, struct fb_info *p, 190 void *dst1, u32 fgcolor, u32 bgcolor) 191{ 192 u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel; 193 u32 ppw = 32/bpp, spitch = (image->width + 7)/8; 194 u32 bit_mask, end_mask, eorx, shift; 195 const char *s = image->data, *src; 196 u32 *dst; 197 const u32 *tab = NULL; 198 int i, j, k; 199 200 switch (bpp) { 201 case 8: 202 tab = cfb_tab8; 203 break; 204 case 16: 205 tab = cfb_tab16; 206 break; 207 case 32: 208 default: 209 tab = cfb_tab32; 210 break; 211 } 212 213 for (i = ppw-1; i--; ) { 214 fgx <<= bpp; 215 bgx <<= bpp; 216 fgx |= fgcolor; 217 bgx |= bgcolor; 218 } 219 220 bit_mask = (1 << ppw) - 1; 221 eorx = fgx ^ bgx; 222 k = image->width/ppw; 223 224 for (i = image->height; i--; ) { 225 dst = dst1; 226 shift = 8; 227 src = s; 228 229 for (j = k; j--; ) { 230 shift -= ppw; 231 end_mask = tab[(*src >> shift) & bit_mask]; 232 *dst++ = (end_mask & eorx) ^ bgx; 233 if (!shift) { 234 shift = 8; 235 src++; 236 } 237 } 238 dst1 += p->fix.line_length; 239 s += spitch; 240 } 241} 242 243void sys_imageblit(struct fb_info *p, const struct fb_image *image) 244{ 245 u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0; 246 u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel; 247 u32 width = image->width; 248 u32 dx = image->dx, dy = image->dy; 249 void *dst1; 250 251 if (p->state != FBINFO_STATE_RUNNING) 252 return; 253 254 bitstart = (dy * p->fix.line_length * 8) + (dx * bpp); 255 start_index = bitstart & (32 - 1); 256 pitch_index = (p->fix.line_length & (bpl - 1)) * 8; 257 258 bitstart /= 8; 259 bitstart &= ~(bpl - 1); 260 dst1 = (void __force *)p->screen_base + bitstart; 261 262 if (p->fbops->fb_sync) 263 p->fbops->fb_sync(p); 264 265 if (image->depth == 1) { 266 if (p->fix.visual == FB_VISUAL_TRUECOLOR || 267 p->fix.visual == FB_VISUAL_DIRECTCOLOR) { 268 fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color]; 269 bgcolor = ((u32*)(p->pseudo_palette))[image->bg_color]; 270 } else { 271 fgcolor = image->fg_color; 272 bgcolor = image->bg_color; 273 } 274 275 if (32 % bpp == 0 && !start_index && !pitch_index && 276 ((width & (32/bpp-1)) == 0) && 277 bpp >= 8 && bpp <= 32) 278 fast_imageblit(image, p, dst1, fgcolor, bgcolor); 279 else 280 slow_imageblit(image, p, dst1, fgcolor, bgcolor, 281 start_index, pitch_index); 282 } else 283 color_imageblit(image, p, dst1, start_index, pitch_index); 284} 285 286EXPORT_SYMBOL(sys_imageblit); 287 288MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>"); 289MODULE_DESCRIPTION("1-bit/8-bit to 1-32 bit color expansion (sys-to-sys)"); 290MODULE_LICENSE("GPL"); 291