diff options
Diffstat (limited to 'drivers/video/console/bitblit.c')
| -rw-r--r-- | drivers/video/console/bitblit.c | 148 |
1 files changed, 94 insertions, 54 deletions
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c index 3c731577fed6..9f70e512b88b 100644 --- a/drivers/video/console/bitblit.c +++ b/drivers/video/console/bitblit.c | |||
| @@ -39,7 +39,7 @@ static inline int get_attribute(struct fb_info *info, u16 c) | |||
| 39 | { | 39 | { |
| 40 | int attribute = 0; | 40 | int attribute = 0; |
| 41 | 41 | ||
| 42 | if (fb_get_color_depth(&info->var) == 1) { | 42 | if (fb_get_color_depth(&info->var, &info->fix) == 1) { |
| 43 | if (attr_underline(c)) | 43 | if (attr_underline(c)) |
| 44 | attribute |= FBCON_ATTRIBUTE_UNDERLINE; | 44 | attribute |= FBCON_ATTRIBUTE_UNDERLINE; |
| 45 | if (attr_reverse(c)) | 45 | if (attr_reverse(c)) |
| @@ -103,42 +103,104 @@ static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy, | |||
| 103 | info->fbops->fb_fillrect(info, ®ion); | 103 | info->fbops->fb_fillrect(info, ®ion); |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | static inline void bit_putcs_aligned(struct vc_data *vc, struct fb_info *info, | ||
| 107 | const u16 *s, u32 attr, u32 cnt, | ||
| 108 | u32 d_pitch, u32 s_pitch, u32 cellsize, | ||
| 109 | struct fb_image *image, u8 *buf, u8 *dst) | ||
| 110 | { | ||
| 111 | u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; | ||
| 112 | u32 idx = vc->vc_font.width >> 3; | ||
| 113 | u8 *src; | ||
| 114 | |||
| 115 | while (cnt--) { | ||
| 116 | src = vc->vc_font.data + (scr_readw(s++)& | ||
| 117 | charmask)*cellsize; | ||
| 118 | |||
| 119 | if (attr) { | ||
| 120 | update_attr(buf, src, attr, vc); | ||
| 121 | src = buf; | ||
| 122 | } | ||
| 123 | |||
| 124 | if (likely(idx == 1)) | ||
| 125 | __fb_pad_aligned_buffer(dst, d_pitch, src, idx, | ||
| 126 | image->height); | ||
| 127 | else | ||
| 128 | fb_pad_aligned_buffer(dst, d_pitch, src, idx, | ||
| 129 | image->height); | ||
| 130 | |||
| 131 | dst += s_pitch; | ||
| 132 | } | ||
| 133 | |||
| 134 | info->fbops->fb_imageblit(info, image); | ||
| 135 | } | ||
| 136 | |||
| 137 | static inline void bit_putcs_unaligned(struct vc_data *vc, | ||
| 138 | struct fb_info *info, const u16 *s, | ||
| 139 | u32 attr, u32 cnt, u32 d_pitch, | ||
| 140 | u32 s_pitch, u32 cellsize, | ||
| 141 | struct fb_image *image, u8 *buf, | ||
| 142 | u8 *dst) | ||
| 143 | { | ||
| 144 | u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; | ||
| 145 | u32 shift_low = 0, mod = vc->vc_font.width % 8; | ||
| 146 | u32 shift_high = 8; | ||
| 147 | u32 idx = vc->vc_font.width >> 3; | ||
| 148 | u8 *src; | ||
| 149 | |||
| 150 | while (cnt--) { | ||
| 151 | src = vc->vc_font.data + (scr_readw(s++)& | ||
| 152 | charmask)*cellsize; | ||
| 153 | |||
| 154 | if (attr) { | ||
| 155 | update_attr(buf, src, attr, vc); | ||
| 156 | src = buf; | ||
| 157 | } | ||
| 158 | |||
| 159 | fb_pad_unaligned_buffer(dst, d_pitch, src, idx, | ||
| 160 | image->height, shift_high, | ||
| 161 | shift_low, mod); | ||
| 162 | shift_low += mod; | ||
| 163 | dst += (shift_low >= 8) ? s_pitch : s_pitch - 1; | ||
| 164 | shift_low &= 7; | ||
| 165 | shift_high = 8 - shift_low; | ||
| 166 | } | ||
| 167 | |||
| 168 | info->fbops->fb_imageblit(info, image); | ||
| 169 | |||
| 170 | } | ||
| 171 | |||
| 106 | static void bit_putcs(struct vc_data *vc, struct fb_info *info, | 172 | static void bit_putcs(struct vc_data *vc, struct fb_info *info, |
| 107 | const unsigned short *s, int count, int yy, int xx, | 173 | const unsigned short *s, int count, int yy, int xx, |
| 108 | int fg, int bg) | 174 | int fg, int bg) |
| 109 | { | 175 | { |
| 110 | unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; | ||
| 111 | unsigned int width = (vc->vc_font.width + 7) >> 3; | ||
| 112 | unsigned int cellsize = vc->vc_font.height * width; | ||
| 113 | unsigned int maxcnt = info->pixmap.size/cellsize; | ||
| 114 | unsigned int scan_align = info->pixmap.scan_align - 1; | ||
| 115 | unsigned int buf_align = info->pixmap.buf_align - 1; | ||
| 116 | unsigned int shift_low = 0, mod = vc->vc_font.width % 8; | ||
| 117 | unsigned int shift_high = 8, pitch, cnt, size, k; | ||
| 118 | unsigned int idx = vc->vc_font.width >> 3; | ||
| 119 | unsigned int attribute = get_attribute(info, scr_readw(s)); | ||
| 120 | struct fb_image image; | 176 | struct fb_image image; |
| 121 | u8 *src, *dst, *buf = NULL; | 177 | u32 width = (vc->vc_font.width + 7)/8; |
| 122 | 178 | u32 cellsize = width * vc->vc_font.height; | |
| 123 | if (attribute) { | 179 | u32 maxcnt = info->pixmap.size/cellsize; |
| 124 | buf = kmalloc(cellsize, GFP_KERNEL); | 180 | u32 scan_align = info->pixmap.scan_align - 1; |
| 125 | if (!buf) | 181 | u32 buf_align = info->pixmap.buf_align - 1; |
| 126 | return; | 182 | u32 mod = vc->vc_font.width % 8, cnt, pitch, size; |
| 127 | } | 183 | u32 attribute = get_attribute(info, scr_readw(s)); |
| 184 | u8 *dst, *buf = NULL; | ||
| 128 | 185 | ||
| 129 | image.fg_color = fg; | 186 | image.fg_color = fg; |
| 130 | image.bg_color = bg; | 187 | image.bg_color = bg; |
| 131 | |||
| 132 | image.dx = xx * vc->vc_font.width; | 188 | image.dx = xx * vc->vc_font.width; |
| 133 | image.dy = yy * vc->vc_font.height; | 189 | image.dy = yy * vc->vc_font.height; |
| 134 | image.height = vc->vc_font.height; | 190 | image.height = vc->vc_font.height; |
| 135 | image.depth = 1; | 191 | image.depth = 1; |
| 136 | 192 | ||
| 193 | if (attribute) { | ||
| 194 | buf = kmalloc(cellsize, GFP_KERNEL); | ||
| 195 | if (!buf) | ||
| 196 | return; | ||
| 197 | } | ||
| 198 | |||
| 137 | while (count) { | 199 | while (count) { |
| 138 | if (count > maxcnt) | 200 | if (count > maxcnt) |
| 139 | cnt = k = maxcnt; | 201 | cnt = maxcnt; |
| 140 | else | 202 | else |
| 141 | cnt = k = count; | 203 | cnt = count; |
| 142 | 204 | ||
| 143 | image.width = vc->vc_font.width * cnt; | 205 | image.width = vc->vc_font.width * cnt; |
| 144 | pitch = ((image.width + 7) >> 3) + scan_align; | 206 | pitch = ((image.width + 7) >> 3) + scan_align; |
| @@ -147,41 +209,18 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info, | |||
| 147 | size &= ~buf_align; | 209 | size &= ~buf_align; |
| 148 | dst = fb_get_buffer_offset(info, &info->pixmap, size); | 210 | dst = fb_get_buffer_offset(info, &info->pixmap, size); |
| 149 | image.data = dst; | 211 | image.data = dst; |
| 150 | if (mod) { | 212 | |
| 151 | while (k--) { | 213 | if (!mod) |
| 152 | src = vc->vc_font.data + (scr_readw(s++)& | 214 | bit_putcs_aligned(vc, info, s, attribute, cnt, pitch, |
| 153 | charmask)*cellsize; | 215 | width, cellsize, &image, buf, dst); |
| 154 | 216 | else | |
| 155 | if (attribute) { | 217 | bit_putcs_unaligned(vc, info, s, attribute, cnt, |
| 156 | update_attr(buf, src, attribute, vc); | 218 | pitch, width, cellsize, &image, |
| 157 | src = buf; | 219 | buf, dst); |
| 158 | } | 220 | |
| 159 | |||
| 160 | fb_pad_unaligned_buffer(dst, pitch, src, idx, | ||
| 161 | image.height, shift_high, | ||
| 162 | shift_low, mod); | ||
| 163 | shift_low += mod; | ||
| 164 | dst += (shift_low >= 8) ? width : width - 1; | ||
| 165 | shift_low &= 7; | ||
| 166 | shift_high = 8 - shift_low; | ||
| 167 | } | ||
| 168 | } else { | ||
| 169 | while (k--) { | ||
| 170 | src = vc->vc_font.data + (scr_readw(s++)& | ||
| 171 | charmask)*cellsize; | ||
| 172 | |||
| 173 | if (attribute) { | ||
| 174 | update_attr(buf, src, attribute, vc); | ||
| 175 | src = buf; | ||
| 176 | } | ||
| 177 | |||
| 178 | fb_pad_aligned_buffer(dst, pitch, src, idx, image.height); | ||
| 179 | dst += width; | ||
| 180 | } | ||
| 181 | } | ||
| 182 | info->fbops->fb_imageblit(info, &image); | ||
| 183 | image.dx += cnt * vc->vc_font.width; | 221 | image.dx += cnt * vc->vc_font.width; |
| 184 | count -= cnt; | 222 | count -= cnt; |
| 223 | s += cnt; | ||
| 185 | } | 224 | } |
| 186 | 225 | ||
| 187 | /* buf is always NULL except when in monochrome mode, so in this case | 226 | /* buf is always NULL except when in monochrome mode, so in this case |
| @@ -189,6 +228,7 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info, | |||
| 189 | NULL pointers just fine */ | 228 | NULL pointers just fine */ |
| 190 | if (unlikely(buf)) | 229 | if (unlikely(buf)) |
| 191 | kfree(buf); | 230 | kfree(buf); |
| 231 | |||
| 192 | } | 232 | } |
| 193 | 233 | ||
| 194 | static void bit_clear_margins(struct vc_data *vc, struct fb_info *info, | 234 | static void bit_clear_margins(struct vc_data *vc, struct fb_info *info, |
