Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.12-rc5 405 lines 11 kB view raw
1/* 2 * linux/drivers/video/console/bitblit.c -- BitBlitting Operation 3 * 4 * Originally from the 'accel_*' routines in drivers/video/console/fbcon.c 5 * 6 * Copyright (C) 2004 Antonino Daplas <adaplas @pol.net> 7 * 8 * This file is subject to the terms and conditions of the GNU General Public 9 * License. See the file COPYING in the main directory of this archive for 10 * more details. 11 */ 12 13#include <linux/config.h> 14#include <linux/module.h> 15#include <linux/string.h> 16#include <linux/fb.h> 17#include <linux/vt_kern.h> 18#include <linux/console.h> 19#include <asm/types.h> 20#include "fbcon.h" 21 22/* 23 * Accelerated handlers. 24 */ 25#define FBCON_ATTRIBUTE_UNDERLINE 1 26#define FBCON_ATTRIBUTE_REVERSE 2 27#define FBCON_ATTRIBUTE_BOLD 4 28 29static inline int real_y(struct display *p, int ypos) 30{ 31 int rows = p->vrows; 32 33 ypos += p->yscroll; 34 return ypos < rows ? ypos : ypos - rows; 35} 36 37 38static inline int get_attribute(struct fb_info *info, u16 c) 39{ 40 int attribute = 0; 41 42 if (fb_get_color_depth(&info->var) == 1) { 43 if (attr_underline(c)) 44 attribute |= FBCON_ATTRIBUTE_UNDERLINE; 45 if (attr_reverse(c)) 46 attribute |= FBCON_ATTRIBUTE_REVERSE; 47 if (attr_bold(c)) 48 attribute |= FBCON_ATTRIBUTE_BOLD; 49 } 50 51 return attribute; 52} 53 54static inline void update_attr(u8 *dst, u8 *src, int attribute, 55 struct vc_data *vc) 56{ 57 int i, offset = (vc->vc_font.height < 10) ? 1 : 2; 58 int width = (vc->vc_font.width + 7) >> 3; 59 unsigned int cellsize = vc->vc_font.height * width; 60 u8 c; 61 62 offset = cellsize - (offset * width); 63 for (i = 0; i < cellsize; i++) { 64 c = src[i]; 65 if (attribute & FBCON_ATTRIBUTE_UNDERLINE && i >= offset) 66 c = 0xff; 67 if (attribute & FBCON_ATTRIBUTE_BOLD) 68 c |= c >> 1; 69 if (attribute & FBCON_ATTRIBUTE_REVERSE) 70 c = ~c; 71 dst[i] = c; 72 } 73} 74 75static void bit_bmove(struct vc_data *vc, struct fb_info *info, int sy, 76 int sx, int dy, int dx, int height, int width) 77{ 78 struct fb_copyarea area; 79 80 area.sx = sx * vc->vc_font.width; 81 area.sy = sy * vc->vc_font.height; 82 area.dx = dx * vc->vc_font.width; 83 area.dy = dy * vc->vc_font.height; 84 area.height = height * vc->vc_font.height; 85 area.width = width * vc->vc_font.width; 86 87 info->fbops->fb_copyarea(info, &area); 88} 89 90static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy, 91 int sx, int height, int width) 92{ 93 int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; 94 struct fb_fillrect region; 95 96 region.color = attr_bgcol_ec(bgshift, vc); 97 region.dx = sx * vc->vc_font.width; 98 region.dy = sy * vc->vc_font.height; 99 region.width = width * vc->vc_font.width; 100 region.height = height * vc->vc_font.height; 101 region.rop = ROP_COPY; 102 103 info->fbops->fb_fillrect(info, &region); 104} 105 106static void bit_putcs(struct vc_data *vc, struct fb_info *info, 107 const unsigned short *s, int count, int yy, int xx, 108 int fg, int bg) 109{ 110 void (*move_unaligned)(struct fb_info *info, struct fb_pixmap *buf, 111 u8 *dst, u32 d_pitch, u8 *src, u32 idx, 112 u32 height, u32 shift_high, u32 shift_low, 113 u32 mod); 114 void (*move_aligned)(struct fb_info *info, struct fb_pixmap *buf, 115 u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, 116 u32 height); 117 unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; 118 unsigned int width = (vc->vc_font.width + 7) >> 3; 119 unsigned int cellsize = vc->vc_font.height * width; 120 unsigned int maxcnt = info->pixmap.size/cellsize; 121 unsigned int scan_align = info->pixmap.scan_align - 1; 122 unsigned int buf_align = info->pixmap.buf_align - 1; 123 unsigned int shift_low = 0, mod = vc->vc_font.width % 8; 124 unsigned int shift_high = 8, pitch, cnt, size, k; 125 unsigned int idx = vc->vc_font.width >> 3; 126 unsigned int attribute = get_attribute(info, scr_readw(s)); 127 struct fb_image image; 128 u8 *src, *dst, *buf = NULL; 129 130 if (attribute) { 131 buf = kmalloc(cellsize, GFP_KERNEL); 132 if (!buf) 133 return; 134 } 135 136 image.fg_color = fg; 137 image.bg_color = bg; 138 139 image.dx = xx * vc->vc_font.width; 140 image.dy = yy * vc->vc_font.height; 141 image.height = vc->vc_font.height; 142 image.depth = 1; 143 144 if (info->pixmap.outbuf && info->pixmap.inbuf) { 145 move_aligned = fb_iomove_buf_aligned; 146 move_unaligned = fb_iomove_buf_unaligned; 147 } else { 148 move_aligned = fb_sysmove_buf_aligned; 149 move_unaligned = fb_sysmove_buf_unaligned; 150 } 151 while (count) { 152 if (count > maxcnt) 153 cnt = k = maxcnt; 154 else 155 cnt = k = count; 156 157 image.width = vc->vc_font.width * cnt; 158 pitch = ((image.width + 7) >> 3) + scan_align; 159 pitch &= ~scan_align; 160 size = pitch * image.height + buf_align; 161 size &= ~buf_align; 162 dst = fb_get_buffer_offset(info, &info->pixmap, size); 163 image.data = dst; 164 if (mod) { 165 while (k--) { 166 src = vc->vc_font.data + (scr_readw(s++)& 167 charmask)*cellsize; 168 169 if (attribute) { 170 update_attr(buf, src, attribute, vc); 171 src = buf; 172 } 173 174 move_unaligned(info, &info->pixmap, dst, pitch, 175 src, idx, image.height, 176 shift_high, shift_low, mod); 177 shift_low += mod; 178 dst += (shift_low >= 8) ? width : width - 1; 179 shift_low &= 7; 180 shift_high = 8 - shift_low; 181 } 182 } else { 183 while (k--) { 184 src = vc->vc_font.data + (scr_readw(s++)& 185 charmask)*cellsize; 186 187 if (attribute) { 188 update_attr(buf, src, attribute, vc); 189 src = buf; 190 } 191 192 move_aligned(info, &info->pixmap, dst, pitch, 193 src, idx, image.height); 194 dst += width; 195 } 196 } 197 info->fbops->fb_imageblit(info, &image); 198 image.dx += cnt * vc->vc_font.width; 199 count -= cnt; 200 } 201 202 /* buf is always NULL except when in monochrome mode, so in this case 203 it's a gain to check buf against NULL even though kfree() handles 204 NULL pointers just fine */ 205 if (unlikely(buf)) 206 kfree(buf); 207} 208 209static void bit_clear_margins(struct vc_data *vc, struct fb_info *info, 210 int bottom_only) 211{ 212 int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; 213 unsigned int cw = vc->vc_font.width; 214 unsigned int ch = vc->vc_font.height; 215 unsigned int rw = info->var.xres - (vc->vc_cols*cw); 216 unsigned int bh = info->var.yres - (vc->vc_rows*ch); 217 unsigned int rs = info->var.xres - rw; 218 unsigned int bs = info->var.yres - bh; 219 struct fb_fillrect region; 220 221 region.color = attr_bgcol_ec(bgshift, vc); 222 region.rop = ROP_COPY; 223 224 if (rw && !bottom_only) { 225 region.dx = info->var.xoffset + rs; 226 region.dy = 0; 227 region.width = rw; 228 region.height = info->var.yres_virtual; 229 info->fbops->fb_fillrect(info, &region); 230 } 231 232 if (bh) { 233 region.dx = info->var.xoffset; 234 region.dy = info->var.yoffset + bs; 235 region.width = rs; 236 region.height = bh; 237 info->fbops->fb_fillrect(info, &region); 238 } 239} 240 241static void bit_cursor(struct vc_data *vc, struct fb_info *info, 242 struct display *p, int mode, int softback_lines, int fg, int bg) 243{ 244 struct fb_cursor cursor; 245 struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par; 246 unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; 247 int w = (vc->vc_font.width + 7) >> 3, c; 248 int y = real_y(p, vc->vc_y); 249 int attribute, use_sw = (vc->vc_cursor_type & 0x10); 250 char *src; 251 252 cursor.set = 0; 253 254 if (softback_lines) { 255 if (y + softback_lines >= vc->vc_rows) { 256 mode = CM_ERASE; 257 ops->cursor_flash = 0; 258 return; 259 } else 260 y += softback_lines; 261 } 262 263 c = scr_readw((u16 *) vc->vc_pos); 264 attribute = get_attribute(info, c); 265 src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height)); 266 267 if (ops->cursor_state.image.data != src || 268 ops->cursor_reset) { 269 ops->cursor_state.image.data = src; 270 cursor.set |= FB_CUR_SETIMAGE; 271 } 272 273 if (attribute) { 274 u8 *dst; 275 276 dst = kmalloc(w * vc->vc_font.height, GFP_ATOMIC); 277 if (!dst) 278 return; 279 kfree(ops->cursor_data); 280 ops->cursor_data = dst; 281 update_attr(dst, src, attribute, vc); 282 src = dst; 283 } 284 285 if (ops->cursor_state.image.fg_color != fg || 286 ops->cursor_state.image.bg_color != bg || 287 ops->cursor_reset) { 288 ops->cursor_state.image.fg_color = fg; 289 ops->cursor_state.image.bg_color = bg; 290 cursor.set |= FB_CUR_SETCMAP; 291 } 292 293 if ((ops->cursor_state.image.dx != (vc->vc_font.width * vc->vc_x)) || 294 (ops->cursor_state.image.dy != (vc->vc_font.height * y)) || 295 ops->cursor_reset) { 296 ops->cursor_state.image.dx = vc->vc_font.width * vc->vc_x; 297 ops->cursor_state.image.dy = vc->vc_font.height * y; 298 cursor.set |= FB_CUR_SETPOS; 299 } 300 301 if (ops->cursor_state.image.height != vc->vc_font.height || 302 ops->cursor_state.image.width != vc->vc_font.width || 303 ops->cursor_reset) { 304 ops->cursor_state.image.height = vc->vc_font.height; 305 ops->cursor_state.image.width = vc->vc_font.width; 306 cursor.set |= FB_CUR_SETSIZE; 307 } 308 309 if (ops->cursor_state.hot.x || ops->cursor_state.hot.y || 310 ops->cursor_reset) { 311 ops->cursor_state.hot.x = cursor.hot.y = 0; 312 cursor.set |= FB_CUR_SETHOT; 313 } 314 315 if (cursor.set & FB_CUR_SETSIZE || 316 vc->vc_cursor_type != p->cursor_shape || 317 ops->cursor_state.mask == NULL || 318 ops->cursor_reset) { 319 char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC); 320 int cur_height, size, i = 0; 321 u8 msk = 0xff; 322 323 if (!mask) 324 return; 325 326 kfree(ops->cursor_state.mask); 327 ops->cursor_state.mask = mask; 328 329 p->cursor_shape = vc->vc_cursor_type; 330 cursor.set |= FB_CUR_SETSHAPE; 331 332 switch (p->cursor_shape & CUR_HWMASK) { 333 case CUR_NONE: 334 cur_height = 0; 335 break; 336 case CUR_UNDERLINE: 337 cur_height = (vc->vc_font.height < 10) ? 1 : 2; 338 break; 339 case CUR_LOWER_THIRD: 340 cur_height = vc->vc_font.height/3; 341 break; 342 case CUR_LOWER_HALF: 343 cur_height = vc->vc_font.height >> 1; 344 break; 345 case CUR_TWO_THIRDS: 346 cur_height = (vc->vc_font.height << 1)/3; 347 break; 348 case CUR_BLOCK: 349 default: 350 cur_height = vc->vc_font.height; 351 break; 352 } 353 size = (vc->vc_font.height - cur_height) * w; 354 while (size--) 355 mask[i++] = ~msk; 356 size = cur_height * w; 357 while (size--) 358 mask[i++] = msk; 359 } 360 361 switch (mode) { 362 case CM_ERASE: 363 ops->cursor_state.enable = 0; 364 break; 365 case CM_DRAW: 366 case CM_MOVE: 367 default: 368 ops->cursor_state.enable = (use_sw) ? 0 : 1; 369 break; 370 } 371 372 cursor.image.data = src; 373 cursor.image.fg_color = ops->cursor_state.image.fg_color; 374 cursor.image.bg_color = ops->cursor_state.image.bg_color; 375 cursor.image.dx = ops->cursor_state.image.dx; 376 cursor.image.dy = ops->cursor_state.image.dy; 377 cursor.image.height = ops->cursor_state.image.height; 378 cursor.image.width = ops->cursor_state.image.width; 379 cursor.hot.x = ops->cursor_state.hot.x; 380 cursor.hot.y = ops->cursor_state.hot.y; 381 cursor.mask = ops->cursor_state.mask; 382 cursor.enable = ops->cursor_state.enable; 383 cursor.image.depth = 1; 384 cursor.rop = ROP_XOR; 385 386 info->fbops->fb_cursor(info, &cursor); 387 388 ops->cursor_reset = 0; 389} 390 391void fbcon_set_bitops(struct fbcon_ops *ops) 392{ 393 ops->bmove = bit_bmove; 394 ops->clear = bit_clear; 395 ops->putcs = bit_putcs; 396 ops->clear_margins = bit_clear_margins; 397 ops->cursor = bit_cursor; 398} 399 400EXPORT_SYMBOL(fbcon_set_bitops); 401 402MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>"); 403MODULE_DESCRIPTION("Bit Blitting Operation"); 404MODULE_LICENSE("GPL"); 405