diff options
-rw-r--r-- | drivers/video/console/bitblit.c | 150 | ||||
-rw-r--r-- | drivers/video/fbmem.c | 10 | ||||
-rw-r--r-- | include/linux/fb.h | 15 |
3 files changed, 109 insertions, 66 deletions
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c index 6550875ef9c5..9f70e512b88b 100644 --- a/drivers/video/console/bitblit.c +++ b/drivers/video/console/bitblit.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, i, 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,45 +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 | if (idx == 1) | ||
179 | for(i=0; i < image.height; i++) | ||
180 | dst[pitch*i] = src[i]; | ||
181 | else | ||
182 | fb_pad_aligned_buffer(dst, pitch, src, idx, image.height); | ||
183 | dst += width; | ||
184 | } | ||
185 | } | ||
186 | info->fbops->fb_imageblit(info, &image); | ||
187 | image.dx += cnt * vc->vc_font.width; | 221 | image.dx += cnt * vc->vc_font.width; |
188 | count -= cnt; | 222 | count -= cnt; |
223 | s += cnt; | ||
189 | } | 224 | } |
190 | 225 | ||
191 | /* 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 |
@@ -193,6 +228,7 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info, | |||
193 | NULL pointers just fine */ | 228 | NULL pointers just fine */ |
194 | if (unlikely(buf)) | 229 | if (unlikely(buf)) |
195 | kfree(buf); | 230 | kfree(buf); |
231 | |||
196 | } | 232 | } |
197 | 233 | ||
198 | 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, |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 71b55070bdb9..70be7009f8af 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -90,15 +90,7 @@ EXPORT_SYMBOL(fb_get_color_depth); | |||
90 | */ | 90 | */ |
91 | void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height) | 91 | void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height) |
92 | { | 92 | { |
93 | int i, j; | 93 | __fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, height); |
94 | |||
95 | for (i = height; i--; ) { | ||
96 | /* s_pitch is a few bytes at the most, memcpy is suboptimal */ | ||
97 | for (j = 0; j < s_pitch; j++) | ||
98 | dst[j] = src[j]; | ||
99 | src += s_pitch; | ||
100 | dst += d_pitch; | ||
101 | } | ||
102 | } | 94 | } |
103 | EXPORT_SYMBOL(fb_pad_aligned_buffer); | 95 | EXPORT_SYMBOL(fb_pad_aligned_buffer); |
104 | 96 | ||
diff --git a/include/linux/fb.h b/include/linux/fb.h index 9a4f035e9fdc..82e39cd0c4fb 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h | |||
@@ -833,6 +833,21 @@ extern int fb_new_modelist(struct fb_info *info); | |||
833 | extern struct fb_info *registered_fb[FB_MAX]; | 833 | extern struct fb_info *registered_fb[FB_MAX]; |
834 | extern int num_registered_fb; | 834 | extern int num_registered_fb; |
835 | 835 | ||
836 | static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, | ||
837 | u8 *src, u32 s_pitch, u32 height) | ||
838 | { | ||
839 | int i, j; | ||
840 | |||
841 | d_pitch -= s_pitch; | ||
842 | |||
843 | for (i = height; i--; ) { | ||
844 | /* s_pitch is a few bytes at the most, memcpy is suboptimal */ | ||
845 | for (j = 0; j < s_pitch; j++) | ||
846 | *dst++ = *src++; | ||
847 | dst += d_pitch; | ||
848 | } | ||
849 | } | ||
850 | |||
836 | /* drivers/video/fbsysfs.c */ | 851 | /* drivers/video/fbsysfs.c */ |
837 | extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev); | 852 | extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev); |
838 | extern void framebuffer_release(struct fb_info *info); | 853 | extern void framebuffer_release(struct fb_info *info); |