Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sysimgblt.c
Go to the documentation of this file.
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 <[email protected]>
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,__func__,## args)
22 #else
23 #define DPRINTK(fmt, args...)
24 #endif
25 
26 static const u32 cfb_tab8_be[] = {
27  0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
28  0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
29  0xff000000,0xff0000ff,0xff00ff00,0xff00ffff,
30  0xffff0000,0xffff00ff,0xffffff00,0xffffffff
31 };
32 
33 static const u32 cfb_tab8_le[] = {
34  0x00000000,0xff000000,0x00ff0000,0xffff0000,
35  0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00,
36  0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff,
37  0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff
38 };
39 
40 static const u32 cfb_tab16_be[] = {
41  0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
42 };
43 
44 static const u32 cfb_tab16_le[] = {
45  0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
46 };
47 
48 static const u32 cfb_tab32[] = {
49  0x00000000, 0xffffffff
50 };
51 
52 static void color_imageblit(const struct fb_image *image, struct fb_info *p,
53  void *dst1, u32 start_index, u32 pitch_index)
54 {
55  /* Draw the penguin */
56  u32 *dst, *dst2;
57  u32 color = 0, val, shift;
58  int i, n, bpp = p->var.bits_per_pixel;
59  u32 null_bits = 32 - bpp;
60  u32 *palette = (u32 *) p->pseudo_palette;
61  const u8 *src = image->data;
62 
63  dst2 = dst1;
64  for (i = image->height; i--; ) {
65  n = image->width;
66  dst = dst1;
67  shift = 0;
68  val = 0;
69 
70  if (start_index) {
71  u32 start_mask = ~(FB_SHIFT_HIGH(p, ~(u32)0,
72  start_index));
73  val = *dst & start_mask;
74  shift = start_index;
75  }
76  while (n--) {
77  if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
78  p->fix.visual == FB_VISUAL_DIRECTCOLOR )
79  color = palette[*src];
80  else
81  color = *src;
82  color <<= FB_LEFT_POS(p, bpp);
83  val |= FB_SHIFT_HIGH(p, color, shift);
84  if (shift >= null_bits) {
85  *dst++ = val;
86 
87  val = (shift == null_bits) ? 0 :
88  FB_SHIFT_LOW(p, color, 32 - shift);
89  }
90  shift += bpp;
91  shift &= (32 - 1);
92  src++;
93  }
94  if (shift) {
95  u32 end_mask = FB_SHIFT_HIGH(p, ~(u32)0, shift);
96 
97  *dst &= end_mask;
98  *dst |= val;
99  }
100  dst1 += p->fix.line_length;
101  if (pitch_index) {
102  dst2 += p->fix.line_length;
103  dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1));
104 
105  start_index += pitch_index;
106  start_index &= 32 - 1;
107  }
108  }
109 }
110 
111 static void slow_imageblit(const struct fb_image *image, struct fb_info *p,
112  void *dst1, u32 fgcolor, u32 bgcolor,
113  u32 start_index, u32 pitch_index)
114 {
115  u32 shift, color = 0, bpp = p->var.bits_per_pixel;
116  u32 *dst, *dst2;
117  u32 val, pitch = p->fix.line_length;
118  u32 null_bits = 32 - bpp;
119  u32 spitch = (image->width+7)/8;
120  const u8 *src = image->data, *s;
121  u32 i, j, l;
122 
123  dst2 = dst1;
124  fgcolor <<= FB_LEFT_POS(p, bpp);
125  bgcolor <<= FB_LEFT_POS(p, bpp);
126 
127  for (i = image->height; i--; ) {
128  shift = val = 0;
129  l = 8;
130  j = image->width;
131  dst = dst1;
132  s = src;
133 
134  /* write leading bits */
135  if (start_index) {
136  u32 start_mask = ~(FB_SHIFT_HIGH(p, ~(u32)0,
137  start_index));
138  val = *dst & start_mask;
139  shift = start_index;
140  }
141 
142  while (j--) {
143  l--;
144  color = (*s & (1 << l)) ? fgcolor : bgcolor;
145  val |= FB_SHIFT_HIGH(p, color, shift);
146 
147  /* Did the bitshift spill bits to the next long? */
148  if (shift >= null_bits) {
149  *dst++ = val;
150  val = (shift == null_bits) ? 0 :
151  FB_SHIFT_LOW(p, color, 32 - shift);
152  }
153  shift += bpp;
154  shift &= (32 - 1);
155  if (!l) { l = 8; s++; };
156  }
157 
158  /* write trailing bits */
159  if (shift) {
160  u32 end_mask = FB_SHIFT_HIGH(p, ~(u32)0, shift);
161 
162  *dst &= end_mask;
163  *dst |= val;
164  }
165 
166  dst1 += pitch;
167  src += spitch;
168  if (pitch_index) {
169  dst2 += pitch;
170  dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1));
171  start_index += pitch_index;
172  start_index &= 32 - 1;
173  }
174 
175  }
176 }
177 
178 /*
179  * fast_imageblit - optimized monochrome color expansion
180  *
181  * Only if: bits_per_pixel == 8, 16, or 32
182  * image->width is divisible by pixel/dword (ppw);
183  * fix->line_legth is divisible by 4;
184  * beginning and end of a scanline is dword aligned
185  */
186 static void fast_imageblit(const struct fb_image *image, struct fb_info *p,
187  void *dst1, u32 fgcolor, u32 bgcolor)
188 {
189  u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel;
190  u32 ppw = 32/bpp, spitch = (image->width + 7)/8;
191  u32 bit_mask, end_mask, eorx, shift;
192  const char *s = image->data, *src;
193  u32 *dst;
194  const u32 *tab = NULL;
195  int i, j, k;
196 
197  switch (bpp) {
198  case 8:
199  tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le;
200  break;
201  case 16:
202  tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le;
203  break;
204  case 32:
205  default:
206  tab = cfb_tab32;
207  break;
208  }
209 
210  for (i = ppw-1; i--; ) {
211  fgx <<= bpp;
212  bgx <<= bpp;
213  fgx |= fgcolor;
214  bgx |= bgcolor;
215  }
216 
217  bit_mask = (1 << ppw) - 1;
218  eorx = fgx ^ bgx;
219  k = image->width/ppw;
220 
221  for (i = image->height; i--; ) {
222  dst = dst1;
223  shift = 8;
224  src = s;
225 
226  for (j = k; j--; ) {
227  shift -= ppw;
228  end_mask = tab[(*src >> shift) & bit_mask];
229  *dst++ = (end_mask & eorx) ^ bgx;
230  if (!shift) {
231  shift = 8;
232  src++;
233  }
234  }
235  dst1 += p->fix.line_length;
236  s += spitch;
237  }
238 }
239 
240 void sys_imageblit(struct fb_info *p, const struct fb_image *image)
241 {
242  u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;
243  u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel;
244  u32 width = image->width;
245  u32 dx = image->dx, dy = image->dy;
246  void *dst1;
247 
249  return;
250 
251  bitstart = (dy * p->fix.line_length * 8) + (dx * bpp);
252  start_index = bitstart & (32 - 1);
253  pitch_index = (p->fix.line_length & (bpl - 1)) * 8;
254 
255  bitstart /= 8;
256  bitstart &= ~(bpl - 1);
257  dst1 = (void __force *)p->screen_base + bitstart;
258 
259  if (p->fbops->fb_sync)
260  p->fbops->fb_sync(p);
261 
262  if (image->depth == 1) {
263  if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
264  p->fix.visual == FB_VISUAL_DIRECTCOLOR) {
265  fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color];
266  bgcolor = ((u32*)(p->pseudo_palette))[image->bg_color];
267  } else {
268  fgcolor = image->fg_color;
269  bgcolor = image->bg_color;
270  }
271 
272  if (32 % bpp == 0 && !start_index && !pitch_index &&
273  ((width & (32/bpp-1)) == 0) &&
274  bpp >= 8 && bpp <= 32)
275  fast_imageblit(image, p, dst1, fgcolor, bgcolor);
276  else
277  slow_imageblit(image, p, dst1, fgcolor, bgcolor,
278  start_index, pitch_index);
279  } else
280  color_imageblit(image, p, dst1, start_index, pitch_index);
281 }
282 
284 
285 MODULE_AUTHOR("Antonino Daplas <[email protected]>");
286 MODULE_DESCRIPTION("1-bit/8-bit to 1-32 bit color expansion (sys-to-sys)");
287 MODULE_LICENSE("GPL");
288