3 * \brief bitmap functions
6 * \author Christian Helmuth <ch12@os.inf.tu-dresden.de>
7 * Frank Mehnert <fm3@os.inf.tu-dresden.de>
8 * Adam Lackorzynski <adam@os.inf.tu-dresden.de> */
10 * (c) 2001-2009 Author(s)
11 * economic rights: Technische Universität Dresden (Germany)
12 * This file is part of TUD:OS and distributed under the terms of the
13 * GNU Lesser General Public License 2.1.
14 * Please see the COPYING-LGPL-2.1 file for details.
18 #include <string.h> /* needed for memmove */
20 #include <l4/sys/cache.h>
22 #include <l4/libgfxbitmap/bitmap.h>
25 static int use_fastmemcpy;
28 #define OFFSET(x, y, ptr, bytepp) ptr += (y) * bwidth + (x) * (bytepp);
31 _bmap16lsb(l4_uint8_t *vfb,
35 l4_uint32_t w, l4_uint32_t h,
36 struct gfxbitmap_offset* offset,
40 l4_uint32_t i, j, k, kmod;
42 nobits += offset->preskip_y
43 * (w + offset->preskip_x + offset->endskip_x);
44 /* length of one line in bmap (bits!) */
46 for (i = 0; i < h; i++) {
47 nobits += offset->preskip_x;
48 for (j = 0; j < w; j++, nobits++) {
51 if ( bmap[k] & (0x01 << kmod) )
52 *(l4_uint16_t*) (&vfb[2*j]) = (l4_uint16_t) (fgc & 0xffff);
54 *(l4_uint16_t*) (&vfb[2*j]) = (l4_uint16_t) (bgc & 0xffff);
57 l4_sys_cache_clean_range((unsigned long)vfb,
58 (unsigned long)vfb + w*2);
65 _bmap16msb(l4_uint8_t *vfb,
69 l4_uint32_t w, l4_uint32_t h,
70 struct gfxbitmap_offset* offset,
74 l4_uint32_t nobits = offset->preskip_y
75 * (w + offset->preskip_x + offset->endskip_x);
77 for (i = 0; i < h; i++)
79 unsigned char mask, *b;
80 nobits += offset->preskip_x;
81 mask = 0x80 >> (nobits % 8);
82 b = bmap + nobits / 8;
83 for (j = 0; j < w; j++, nobits++)
85 /* gcc is able to code the entire loop without using any jump
86 * if compiled with -march=i686 (uses cmov instructions then) */
87 *(l4_uint16_t*) (&vfb[2*j]) = (*b & mask)
88 ? (l4_uint16_t) (fgc & 0xffff)
89 : (l4_uint16_t) (bgc & 0xffff);
91 mask = (mask >> 1) | (mask << 7); /* gcc optimizes this into ROR */
94 l4_sys_cache_clean_range((unsigned long)vfb,
95 (unsigned long)vfb + w*2);
98 nobits += offset->endskip_x;
103 _bmap24lsb(l4_uint8_t *vfb,
107 l4_uint32_t w, l4_uint32_t h,
108 struct gfxbitmap_offset* offset,
111 l4_uint32_t nobits=0;
112 l4_uint32_t i,j, k,kmod;
114 nobits += offset->preskip_y
115 * (w + offset->preskip_x + offset->endskip_x);
116 /* length of one line in bmap (bits!) */
118 for (i = 0; i < h; i++) {
119 nobits += offset->preskip_x;
120 for (j = 0; j < w; j++, nobits++) {
123 if ( bmap[k] & (0x01 << kmod) ) {
124 *(l4_uint16_t*) (&vfb[3*j]) = (l4_uint16_t) (fgc & 0xffff);
125 vfb[3*j+2] = (l4_uint8_t) (fgc >> 16);
128 *(l4_uint16_t*) (&vfb[3*j]) = (l4_uint16_t) (bgc & 0xffff);
129 vfb[3*j+2] = (l4_uint8_t) (bgc >> 16);
133 l4_sys_cache_clean_range((unsigned long)vfb,
134 (unsigned long)vfb + w*3);
141 _bmap24msb(l4_uint8_t *vfb,
145 l4_uint32_t w, l4_uint32_t h,
146 struct gfxbitmap_offset* offset,
149 l4_uint32_t nobits=0;
150 l4_uint32_t i,j, k,kmod;
152 nobits += offset->preskip_y
153 * (w + offset->preskip_x + offset->endskip_x);
154 /* length of one line in bmap (bits!) */
156 for (i = 0; i < h; i++) {
157 nobits += offset->preskip_x;
158 for (j = 0; j < w; j++, nobits++) {
161 if ( bmap[k] & (0x80 >> kmod) ) {
162 *(l4_uint16_t*) (&vfb[3*j]) = (l4_uint16_t) (fgc & 0xffff);
163 vfb[3*j+2] = (l4_uint8_t) (fgc >> 16);
166 *(l4_uint16_t*) (&vfb[3*j]) = (l4_uint16_t) (bgc & 0xffff);
167 vfb[3*j+2] = (l4_uint8_t) (bgc >> 16);
171 l4_sys_cache_clean_range((unsigned long)vfb,
172 (unsigned long)vfb + w*3);
175 /* length of one line in bmap parsed */
176 nobits += offset->endskip_x;
181 _bmap32lsb(l4_uint8_t *vfb,
185 l4_uint32_t w, l4_uint32_t h,
186 struct gfxbitmap_offset* offset,
189 l4_uint32_t nobits=0;
190 l4_uint32_t i,j, k,kmod;
192 nobits += offset->preskip_y
193 * (w + offset->preskip_x + offset->endskip_x);
194 /* length of one line in bmap (bits!) */
196 for (i = 0; i < h; i++) {
197 nobits += offset->preskip_x;
198 for (j = 0; j < w; j++, nobits++) {
199 l4_uint32_t *dest = (l4_uint32_t*)&vfb[4*j];
202 *dest = (bmap[k] & (0x01 << kmod))
207 l4_sys_cache_clean_range((unsigned long)vfb,
208 (unsigned long)vfb + w*4);
215 _bmap32msb(l4_uint8_t *vfb,
219 l4_uint32_t w, l4_uint32_t h,
220 struct gfxbitmap_offset* offset,
223 l4_uint32_t nobits=0;
224 l4_uint32_t i,j,k,kmod;
226 nobits += offset->preskip_y
227 * (w + offset->preskip_x + offset->endskip_x);
228 /* length of one line in bmap (bits!) */
230 for (i = 0; i < h; i++) {
231 nobits += offset->preskip_x;
232 for (j = 0; j < w; j++, nobits++) {
235 if ( bmap[k] & (0x80 >> kmod) )
236 *(l4_uint32_t*) (&vfb[4*j]) = (l4_uint32_t) (fgc & 0x00ffffff);
238 *(l4_uint32_t*) (&vfb[4*j]) = (l4_uint32_t) (bgc & 0x00ffffff);
241 l4_sys_cache_clean_range((unsigned long)vfb,
242 (unsigned long)vfb + w*4);
245 /* length of one line in bmap parsed */
246 nobits += offset->endskip_x;
251 _set16(l4_uint8_t *dest,
253 l4_uint32_t w, l4_uint32_t h,
254 struct gfxbitmap_offset* offset,
261 if (use_fastmemcpy && (w % 4 == 0))
264 for (i = 0; i < h; i++)
267 pmap += 2 * offset->preskip_x;
268 asm volatile("xorl %%edx,%%edx \n\t"
270 "movq (%%esi,%%edx,8),%%mm0 \n\t"
271 "movntq %%mm0,(%%edi,%%edx,8) \n\t"
275 : "=c"(dummy), "=d"(dummy)
276 : "c"(w/4), "S"(pmap), "D"(dest));
280 asm ("sfence; emms");
285 for (i = 0; i < h; i++)
287 pmap += 2 * offset->preskip_x;
288 memcpy(dest, pmap, w*2);
290 l4_sys_cache_clean_range((unsigned long)dest,
291 (unsigned long)dest + w*2);
300 _set24(l4_uint8_t *dest,
302 l4_uint32_t w, l4_uint32_t h,
303 struct gfxbitmap_offset* offset,
309 for (i = 0; i < h; i++)
311 pmap += 3 * offset->preskip_x;
312 memcpy(dest, pmap, w*3);
314 l4_sys_cache_clean_range((unsigned long)dest,
315 (unsigned long)dest + w*3);
323 _set32(l4_uint8_t *dest,
325 l4_uint32_t w, l4_uint32_t h,
326 struct gfxbitmap_offset* offset,
332 for (i = 0; i < h; i++)
334 pmap += 4 * offset->preskip_x;
335 memcpy(dest, pmap, w*4);
337 l4_sys_cache_clean_range((unsigned long)dest,
338 (unsigned long)dest + w*4);
346 _copy16(l4_uint8_t *dest,
348 l4_int16_t x, l4_int16_t y,
349 l4_int16_t dx, l4_int16_t dy,
350 l4_uint32_t w, l4_uint32_t h,
355 if (dy == y && dx == x)
360 OFFSET( x, y, src, 2);
361 OFFSET(dx, dy, dest, 2);
362 for (i = 0; i < h; i++)
364 /* memmove can deal with overlapping regions */
365 memmove(dest, src, 2*w);
372 OFFSET( x, y + h - 1, src, 2);
373 OFFSET(dx, dy + h - 1, dest, 2);
374 for (i = 0; i < h; i++)
376 /* memmove can deal with overlapping regions */
377 memmove(dest, src, 2*w);
385 _copy24(l4_uint8_t *dest,
387 l4_int16_t x, l4_int16_t y,
388 l4_int16_t dx, l4_int16_t dy,
389 l4_uint32_t w, l4_uint32_t h,
395 if (y == dy && dx >= x) { /* tricky */
399 /* my way: start right go left */
400 OFFSET( x, y, src, 3);
401 OFFSET(dx, dy, dest, 3);
402 for (i = 0; i < h; i++) {
403 for (j = w; j >= 0; --j) {
404 *(l4_uint16_t*) (&dest[3*j]) = *(l4_uint16_t*) (&src[3*j]);
405 dest[3*j+2] = src[3*j+2];
412 else { /* copy from top to bottom */
414 OFFSET( x, y, src, 3);
415 OFFSET(dx, dy, dest, 3);
416 for (i = 0; i < h; i++) {
417 for (j = 0; j < w; j++) {
418 *(l4_uint16_t*) (&dest[3*j]) = *(l4_uint16_t*) (&src[3*j]);
419 dest[3*j+2] = src[3*j+2];
426 else { /* copy from bottom to top */
427 OFFSET( x, y + h, src, 3);
428 OFFSET(dx, dy + h, dest, 3);
429 for (i = 0; i < h; i++) {
433 for (j = 0; j < w; j++) {
434 *(l4_uint16_t*) (&dest[3*j]) = *(l4_uint16_t*) (&src[3*j]);
435 dest[3*j+2] = src[3*j+2];
442 _copy32(l4_uint8_t *dest,
444 l4_int16_t x, l4_int16_t y,
445 l4_int16_t dx, l4_int16_t dy,
446 l4_uint32_t w, l4_uint32_t h,
452 if (y == dy && dx >= x) { /* tricky */
456 /* my way: start right go left */
457 OFFSET( x, y, src, 4);
458 OFFSET(dx, dy, dest, 4);
459 for (i = 0; i < h; i++) {
460 for (j = w; j >= 0; --j)
461 *(l4_uint32_t*) (&dest[4*j]) = *(l4_uint32_t*) (&src[4*j]);
467 else { /* copy from top to bottom */
469 OFFSET( x, y, src, 4);
470 OFFSET(dx, dy, dest, 4);
471 for (i = 0; i < h; i++) {
472 for (j = 0; j < w; j++)
473 *(l4_uint32_t*) (&dest[4*j]) = *(l4_uint32_t*) (&src[4*j]);
479 else { /* copy from bottom to top */
481 OFFSET( x, y + h, src, 4);
482 OFFSET(dx, dy + h, dest, 4);
483 for (i = 0; i < h; i++) {
486 for (j = 0; j < w; j++)
487 *(l4_uint32_t*) (&dest[4*j]) = *(l4_uint32_t*) (&src[4*j]);
493 _fill16(l4_uint8_t *vfb,
494 l4_uint32_t w, l4_uint32_t h,
500 for (i = 0; i < h; i++)
502 for (j = 0; j < w; j++)
503 *(l4_uint16_t*) (&vfb[2*j]) = (l4_uint16_t)color;
509 _fill24(l4_uint8_t *vfb,
510 l4_uint32_t w, l4_uint32_t h,
516 for (i = 0; i < h; i++) {
517 for (j = 0; j < w; j++) {
518 *(l4_uint16_t*) (&vfb[3*j ]) = (l4_uint16_t)color;
519 vfb[3*j+2] = (l4_uint8_t) (color >> 16);
526 _fill32(l4_uint8_t *vfb,
527 l4_uint32_t w, l4_uint32_t h,
533 for (i = 0; i < h; i++) {
534 for (j = 0; j < w; j++)
535 *(l4_uint32_t*) (&vfb[4*j]) = (l4_uint32_t)color;
541 gfxbitmap_fill(l4_uint8_t *vfb, l4re_video_view_info_t *vi,
542 int x, int y, int w, int h, unsigned color)
544 unsigned bwidth = vi->bytes_per_line;
545 OFFSET(x, y, vfb, vi->pixel_info.bytes_per_pixel);
547 switch (vi->pixel_info.bytes_per_pixel)
550 _fill32(vfb, w, h, color, vi->bytes_per_line);
553 _fill24(vfb, w, h, color, vi->bytes_per_line);
557 _fill16(vfb, w, h, color, vi->bytes_per_line);
562 gfxbitmap_bmap(l4_uint8_t *vfb, l4re_video_view_info_t *vi,
563 l4_int16_t x, l4_int16_t y, l4_uint32_t w,
564 l4_uint32_t h, l4_uint8_t *bmap, l4_uint32_t fgc, l4_uint32_t bgc,
565 struct gfxbitmap_offset* offset, l4_uint8_t mode)
567 l4_uint32_t bwidth = vi->bytes_per_line;
568 OFFSET(x, y, vfb, vi->pixel_info.bytes_per_pixel);
572 case pSLIM_BMAP_START_MSB:
573 switch (vi->pixel_info.bytes_per_pixel)
576 _bmap32msb(vfb, bmap, fgc, bgc, w, h, offset, bwidth);
579 _bmap24msb(vfb, bmap, fgc, bgc, w, h, offset, bwidth);
583 _bmap16msb(vfb, bmap, fgc, bgc, w, h, offset, bwidth);
586 case pSLIM_BMAP_START_LSB:
587 default: /* `start at least significant' bit is default */
588 switch (vi->pixel_info.bytes_per_pixel)
591 _bmap32lsb(vfb, bmap, fgc, bgc, w, h, offset, bwidth);
594 _bmap24lsb(vfb, bmap, fgc, bgc, w, h, offset, bwidth);
598 _bmap16lsb(vfb, bmap, fgc, bgc, w, h, offset, bwidth);
604 gfxbitmap_set(l4_uint8_t *vfb, l4re_video_view_info_t *vi,
605 l4_int16_t x, l4_int16_t y, l4_uint32_t w,
606 l4_uint32_t h, l4_uint32_t xoffs, l4_uint32_t yoffs,
607 l4_uint8_t *pmap, struct gfxbitmap_offset* offset,
610 l4_uint32_t bwidth = vi->bytes_per_line;
612 OFFSET(x+xoffs, y+yoffs, vfb, vi->pixel_info.bytes_per_pixel);
614 switch (vi->pixel_info.bytes_per_pixel)
617 _set32(vfb, pmap, w, h, offset, bwidth, pwidth);
620 _set24(vfb, pmap, w, h, offset, bwidth, pwidth);
624 _set16(vfb, pmap, w, h, offset, bwidth, pwidth);
629 gfxbitmap_copy(l4_uint8_t *dest, l4_uint8_t *src, l4re_video_view_info_t *vi,
630 int x, int y, int w, int h, int dx, int dy)
632 switch (vi->pixel_info.bytes_per_pixel)
635 _copy32(dest, src, x, y, dx, dy, w, h, vi->bytes_per_line);
638 _copy24(dest, src, x, y, dx, dy, w, h, vi->bytes_per_line);
642 _copy16(dest, src, x, y, dx, dy, w, h, vi->bytes_per_line);
646 gfxbitmap_color_pix_t
647 gfxbitmap_convert_color(l4re_video_view_info_t *vi, gfxbitmap_color_t rgb)
649 switch (l4re_video_bits_per_pixel(&vi->pixel_info))
653 return rgb & 0x00FFFFFF;
656 return (((rgb >> (16 + 8 - vi->pixel_info.r.size)) & ((1 << vi->pixel_info.r.size)-1)) << vi->pixel_info.r.shift)
657 | (((rgb >> ( 8 + 8 - vi->pixel_info.g.size)) & ((1 << vi->pixel_info.g.size)-1)) << vi->pixel_info.g.shift)
658 | (((rgb >> ( 0 + 8 - vi->pixel_info.b.size)) & ((1 << vi->pixel_info.b.size)-1)) << vi->pixel_info.b.shift);
662 return ((rgb & 0x00F80000) >> 8)
663 | ((rgb & 0x0000FC00) >> 5)
664 | ((rgb & 0x000000F8) >> 3);