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>
24 static int use_fastmemcpy;
26 #define OFFSET(x, y, ptr, bytepp) ptr += (y) * bwidth + (x) * (bytepp);
29 _bmap16lsb(l4_uint8_t *vfb,
33 l4_uint32_t w, l4_uint32_t h,
34 struct gfxbitmap_offset* offset,
38 l4_uint32_t i, j, k, kmod;
40 nobits += offset->preskip_y
41 * (w + offset->preskip_x + offset->endskip_x);
42 /* length of one line in bmap (bits!) */
44 for (i = 0; i < h; i++) {
45 nobits += offset->preskip_x;
46 for (j = 0; j < w; j++, nobits++) {
49 if ( bmap[k] & (0x01 << kmod) )
50 *(l4_uint16_t*) (&vfb[2*j]) = (l4_uint16_t) (fgc & 0xffff);
52 *(l4_uint16_t*) (&vfb[2*j]) = (l4_uint16_t) (bgc & 0xffff);
55 l4_sys_cache_clean_range((unsigned long)vfb,
56 (unsigned long)vfb + w*2);
63 _bmap16msb(l4_uint8_t *vfb,
67 l4_uint32_t w, l4_uint32_t h,
68 struct gfxbitmap_offset* offset,
72 l4_uint32_t nobits = offset->preskip_y
73 * (w + offset->preskip_x + offset->endskip_x);
75 for (i = 0; i < h; i++)
77 unsigned char mask, *b;
78 nobits += offset->preskip_x;
79 mask = 0x80 >> (nobits % 8);
80 b = bmap + nobits / 8;
81 for (j = 0; j < w; j++, nobits++)
83 /* gcc is able to code the entire loop without using any jump
84 * if compiled with -march=i686 (uses cmov instructions then) */
85 *(l4_uint16_t*) (&vfb[2*j]) = (*b & mask)
86 ? (l4_uint16_t) (fgc & 0xffff)
87 : (l4_uint16_t) (bgc & 0xffff);
89 mask = (mask >> 1) | (mask << 7); /* gcc optimizes this into ROR */
92 l4_sys_cache_clean_range((unsigned long)vfb,
93 (unsigned long)vfb + w*2);
96 nobits += offset->endskip_x;
101 _bmap24lsb(l4_uint8_t *vfb,
105 l4_uint32_t w, l4_uint32_t h,
106 struct gfxbitmap_offset* offset,
109 l4_uint32_t nobits=0;
110 l4_uint32_t i,j, k,kmod;
112 nobits += offset->preskip_y
113 * (w + offset->preskip_x + offset->endskip_x);
114 /* length of one line in bmap (bits!) */
116 for (i = 0; i < h; i++) {
117 nobits += offset->preskip_x;
118 for (j = 0; j < w; j++, nobits++) {
121 if ( bmap[k] & (0x01 << kmod) ) {
122 *(l4_uint16_t*) (&vfb[3*j]) = (l4_uint16_t) (fgc & 0xffff);
123 vfb[3*j+2] = (l4_uint8_t) (fgc >> 16);
126 *(l4_uint16_t*) (&vfb[3*j]) = (l4_uint16_t) (bgc & 0xffff);
127 vfb[3*j+2] = (l4_uint8_t) (bgc >> 16);
131 l4_sys_cache_clean_range((unsigned long)vfb,
132 (unsigned long)vfb + w*3);
139 _bmap24msb(l4_uint8_t *vfb,
143 l4_uint32_t w, l4_uint32_t h,
144 struct gfxbitmap_offset* offset,
147 l4_uint32_t nobits=0;
148 l4_uint32_t i,j, k,kmod;
150 nobits += offset->preskip_y
151 * (w + offset->preskip_x + offset->endskip_x);
152 /* length of one line in bmap (bits!) */
154 for (i = 0; i < h; i++) {
155 nobits += offset->preskip_x;
156 for (j = 0; j < w; j++, nobits++) {
159 if ( bmap[k] & (0x80 >> kmod) ) {
160 *(l4_uint16_t*) (&vfb[3*j]) = (l4_uint16_t) (fgc & 0xffff);
161 vfb[3*j+2] = (l4_uint8_t) (fgc >> 16);
164 *(l4_uint16_t*) (&vfb[3*j]) = (l4_uint16_t) (bgc & 0xffff);
165 vfb[3*j+2] = (l4_uint8_t) (bgc >> 16);
169 l4_sys_cache_clean_range((unsigned long)vfb,
170 (unsigned long)vfb + w*3);
173 /* length of one line in bmap parsed */
174 nobits += offset->endskip_x;
179 _bmap32lsb(l4_uint8_t *vfb,
183 l4_uint32_t w, l4_uint32_t h,
184 struct gfxbitmap_offset* offset,
187 l4_uint32_t nobits=0;
188 l4_uint32_t i,j, k,kmod;
190 nobits += offset->preskip_y
191 * (w + offset->preskip_x + offset->endskip_x);
192 /* length of one line in bmap (bits!) */
194 for (i = 0; i < h; i++) {
195 nobits += offset->preskip_x;
196 for (j = 0; j < w; j++, nobits++) {
197 l4_uint32_t *dest = (l4_uint32_t*)&vfb[4*j];
200 *dest = (bmap[k] & (0x01 << kmod))
205 l4_sys_cache_clean_range((unsigned long)vfb,
206 (unsigned long)vfb + w*4);
213 _bmap32msb(l4_uint8_t *vfb,
217 l4_uint32_t w, l4_uint32_t h,
218 struct gfxbitmap_offset* offset,
221 l4_uint32_t nobits=0;
222 l4_uint32_t i,j,k,kmod;
224 nobits += offset->preskip_y
225 * (w + offset->preskip_x + offset->endskip_x);
226 /* length of one line in bmap (bits!) */
228 for (i = 0; i < h; i++) {
229 nobits += offset->preskip_x;
230 for (j = 0; j < w; j++, nobits++) {
233 if ( bmap[k] & (0x80 >> kmod) )
234 *(l4_uint32_t*) (&vfb[4*j]) = (l4_uint32_t) (fgc & 0x00ffffff);
236 *(l4_uint32_t*) (&vfb[4*j]) = (l4_uint32_t) (bgc & 0x00ffffff);
239 l4_sys_cache_clean_range((unsigned long)vfb,
240 (unsigned long)vfb + w*4);
243 /* length of one line in bmap parsed */
244 nobits += offset->endskip_x;
249 _set16(l4_uint8_t *dest,
251 l4_uint32_t w, l4_uint32_t h,
252 struct gfxbitmap_offset* offset,
259 if (use_fastmemcpy && (w % 4 == 0))
262 for (i = 0; i < h; i++)
265 pmap += 2 * offset->preskip_x;
266 asm volatile("xorl %%edx,%%edx \n\t"
268 "movq (%%esi,%%edx,8),%%mm0 \n\t"
269 "movntq %%mm0,(%%edi,%%edx,8) \n\t"
273 : "=c"(dummy), "=d"(dummy)
274 : "c"(w/4), "S"(pmap), "D"(dest));
278 asm ("sfence; emms");
283 for (i = 0; i < h; i++)
285 pmap += 2 * offset->preskip_x;
286 memcpy(dest, pmap, w*2);
288 l4_sys_cache_clean_range((unsigned long)dest,
289 (unsigned long)dest + w*2);
298 _set24(l4_uint8_t *dest,
300 l4_uint32_t w, l4_uint32_t h,
301 struct gfxbitmap_offset* offset,
307 for (i = 0; i < h; i++)
309 pmap += 3 * offset->preskip_x;
310 memcpy(dest, pmap, w*3);
312 l4_sys_cache_clean_range((unsigned long)dest,
313 (unsigned long)dest + w*3);
321 _set32(l4_uint8_t *dest,
323 l4_uint32_t w, l4_uint32_t h,
324 struct gfxbitmap_offset* offset,
330 for (i = 0; i < h; i++)
332 pmap += 4 * offset->preskip_x;
333 memcpy(dest, pmap, w*4);
335 l4_sys_cache_clean_range((unsigned long)dest,
336 (unsigned long)dest + w*4);
344 _copy16(l4_uint8_t *dest,
346 l4_int16_t x, l4_int16_t y,
347 l4_int16_t dx, l4_int16_t dy,
348 l4_uint32_t w, l4_uint32_t h,
353 if (dy == y && dx == x)
358 OFFSET( x, y, src, 2);
359 OFFSET(dx, dy, dest, 2);
360 for (i = 0; i < h; i++)
362 /* memmove can deal with overlapping regions */
363 memmove(dest, src, 2*w);
370 OFFSET( x, y + h - 1, src, 2);
371 OFFSET(dx, dy + h - 1, dest, 2);
372 for (i = 0; i < h; i++)
374 /* memmove can deal with overlapping regions */
375 memmove(dest, src, 2*w);
383 _copy24(l4_uint8_t *dest,
385 l4_int16_t x, l4_int16_t y,
386 l4_int16_t dx, l4_int16_t dy,
387 l4_uint32_t w, l4_uint32_t h,
393 if (y == dy && dx >= x) { /* tricky */
397 /* my way: start right go left */
398 OFFSET( x, y, src, 3);
399 OFFSET(dx, dy, dest, 3);
400 for (i = 0; i < h; i++) {
401 for (j = w; j >= 0; --j) {
402 *(l4_uint16_t*) (&dest[3*j]) = *(l4_uint16_t*) (&src[3*j]);
403 dest[3*j+2] = src[3*j+2];
410 else { /* copy from top to bottom */
412 OFFSET( x, y, src, 3);
413 OFFSET(dx, dy, dest, 3);
414 for (i = 0; i < h; i++) {
415 for (j = 0; j < w; j++) {
416 *(l4_uint16_t*) (&dest[3*j]) = *(l4_uint16_t*) (&src[3*j]);
417 dest[3*j+2] = src[3*j+2];
424 else { /* copy from bottom to top */
425 OFFSET( x, y + h, src, 3);
426 OFFSET(dx, dy + h, dest, 3);
427 for (i = 0; i < h; i++) {
431 for (j = 0; j < w; j++) {
432 *(l4_uint16_t*) (&dest[3*j]) = *(l4_uint16_t*) (&src[3*j]);
433 dest[3*j+2] = src[3*j+2];
440 _copy32(l4_uint8_t *dest,
442 l4_int16_t x, l4_int16_t y,
443 l4_int16_t dx, l4_int16_t dy,
444 l4_uint32_t w, l4_uint32_t h,
450 if (y == dy && dx >= x) { /* tricky */
454 /* my way: start right go left */
455 OFFSET( x, y, src, 4);
456 OFFSET(dx, dy, dest, 4);
457 for (i = 0; i < h; i++) {
458 for (j = w; j >= 0; --j)
459 *(l4_uint32_t*) (&dest[4*j]) = *(l4_uint32_t*) (&src[4*j]);
465 else { /* copy from top to bottom */
467 OFFSET( x, y, src, 4);
468 OFFSET(dx, dy, dest, 4);
469 for (i = 0; i < h; i++) {
470 for (j = 0; j < w; j++)
471 *(l4_uint32_t*) (&dest[4*j]) = *(l4_uint32_t*) (&src[4*j]);
477 else { /* copy from bottom to top */
479 OFFSET( x, y + h, src, 4);
480 OFFSET(dx, dy + h, dest, 4);
481 for (i = 0; i < h; i++) {
484 for (j = 0; j < w; j++)
485 *(l4_uint32_t*) (&dest[4*j]) = *(l4_uint32_t*) (&src[4*j]);
491 _fill16(l4_uint8_t *vfb,
492 l4_uint32_t w, l4_uint32_t h,
498 for (i = 0; i < h; i++)
500 for (j = 0; j < w; j++)
501 *(l4_uint16_t*) (&vfb[2*j]) = (l4_uint16_t)color;
507 _fill24(l4_uint8_t *vfb,
508 l4_uint32_t w, l4_uint32_t h,
514 for (i = 0; i < h; i++) {
515 for (j = 0; j < w; j++) {
516 *(l4_uint16_t*) (&vfb[3*j ]) = (l4_uint16_t)color;
517 vfb[3*j+2] = (l4_uint8_t) (color >> 16);
524 _fill32(l4_uint8_t *vfb,
525 l4_uint32_t w, l4_uint32_t h,
531 for (i = 0; i < h; i++) {
532 for (j = 0; j < w; j++)
533 *(l4_uint32_t*) (&vfb[4*j]) = (l4_uint32_t)color;
539 gfxbitmap_fill(l4_uint8_t *vfb, l4re_video_view_info_t *vi,
540 int x, int y, int w, int h, unsigned color)
542 unsigned bwidth = vi->bytes_per_line;
543 OFFSET(x, y, vfb, vi->pixel_info.bytes_per_pixel);
545 switch (l4re_video_bits_per_pixel(&vi->pixel_info))
548 _fill24(vfb, w, h, color, vi->bytes_per_line);
551 _fill32(vfb, w, h, color, vi->bytes_per_line);
555 _fill16(vfb, w, h, color, vi->bytes_per_line);
560 gfxbitmap_bmap(l4_uint8_t *vfb, l4re_video_view_info_t *vi,
561 l4_int16_t x, l4_int16_t y, l4_uint32_t w,
562 l4_uint32_t h, l4_uint8_t *bmap, l4_uint32_t fgc, l4_uint32_t bgc,
563 struct gfxbitmap_offset* offset, l4_uint8_t mode)
565 l4_uint32_t bwidth = vi->bytes_per_line;
566 OFFSET(x, y, vfb, vi->pixel_info.bytes_per_pixel);
570 case pSLIM_BMAP_START_MSB:
571 switch (l4re_video_bits_per_pixel(&vi->pixel_info))
574 _bmap32msb(vfb, bmap, fgc, bgc, w, h, offset, bwidth);
577 _bmap24msb(vfb, bmap, fgc, bgc, w, h, offset, bwidth);
581 _bmap16msb(vfb, bmap, fgc, bgc, w, h, offset, bwidth);
584 case pSLIM_BMAP_START_LSB:
585 default: /* `start at least significant' bit is default */
586 switch (l4re_video_bits_per_pixel(&vi->pixel_info))
589 _bmap32lsb(vfb, bmap, fgc, bgc, w, h, offset, bwidth);
592 _bmap24lsb(vfb, bmap, fgc, bgc, w, h, offset, bwidth);
596 _bmap16lsb(vfb, bmap, fgc, bgc, w, h, offset, bwidth);
602 gfxbitmap_set(l4_uint8_t *vfb, l4re_video_view_info_t *vi,
603 l4_int16_t x, l4_int16_t y, l4_uint32_t w,
604 l4_uint32_t h, l4_uint32_t xoffs, l4_uint32_t yoffs,
605 l4_uint8_t *pmap, struct gfxbitmap_offset* offset,
608 l4_uint32_t bwidth = vi->bytes_per_line;
610 OFFSET(x+xoffs, y+yoffs, vfb, vi->pixel_info.bytes_per_pixel);
612 switch (l4re_video_bits_per_pixel(&vi->pixel_info))
615 _set32(vfb, pmap, w, h, offset, bwidth, pwidth);
618 _set24(vfb, pmap, w, h, offset, bwidth, pwidth);
622 _set16(vfb, pmap, w, h, offset, bwidth, pwidth);
627 gfxbitmap_copy(l4_uint8_t *dest, l4_uint8_t *src, l4re_video_view_info_t *vi,
628 int x, int y, int w, int h, int dx, int dy)
630 switch (l4re_video_bits_per_pixel(&vi->pixel_info))
633 _copy32(dest, src, x, y, dx, dy, w, h, vi->bytes_per_line);
636 _copy24(dest, src, x, y, dx, dy, w, h, vi->bytes_per_line);
640 _copy16(dest, src, x, y, dx, dy, w, h, vi->bytes_per_line);
644 gfxbitmap_color_pix_t
645 gfxbitmap_convert_color(l4re_video_view_info_t *vi, gfxbitmap_color_t rgb)
647 switch (l4re_video_bits_per_pixel(&vi->pixel_info))
651 return rgb & 0x00FFFFFF;
654 return (((rgb >> (16 + 8 - vi->pixel_info.r.size)) & ((1 << vi->pixel_info.r.size)-1)) << vi->pixel_info.r.shift)
655 | (((rgb >> ( 8 + 8 - vi->pixel_info.g.size)) & ((1 << vi->pixel_info.g.size)-1)) << vi->pixel_info.g.shift)
656 | (((rgb >> ( 0 + 8 - vi->pixel_info.b.size)) & ((1 << vi->pixel_info.b.size)-1)) << vi->pixel_info.b.shift);
660 return ((rgb & 0x00F80000) >> 8)
661 | ((rgb & 0x0000FC00) >> 5)
662 | ((rgb & 0x000000F8) >> 3);