1 /*****************************************************************************
2 * This file is part of gfxprim library. *
4 * Gfxprim is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU Lesser General Public *
6 * License as published by the Free Software Foundation; either *
7 * version 2.1 of the License, or (at your option) any later version. *
9 * Gfxprim is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * Lesser General Public License for more details. *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with gfxprim; if not, write to the Free Software *
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301 USA *
19 * Copyright (C) 2009-2010 Jiri "BlueBear" Dluhos *
20 * <jiri.bluebear.dluhos@gmail.com> *
22 * Copyright (C) 2009-2013 Cyril Hrubis <metan@ucw.cz> *
24 *****************************************************************************/
29 #include "GP_WritePixel.h"
31 static const uint8_t bytes_1BPP
[] = {0x00, 0xff};
33 void GP_WritePixels_1BPP_LE(void *start
, uint8_t off
,
34 size_t cnt
, unsigned int val
)
38 /* Write start of the line */
43 GP_SET_BITS1_ALIGNED(1, 1, start
, val
);
48 GP_SET_BITS1_ALIGNED(2, 1, start
, val
);
53 GP_SET_BITS1_ALIGNED(3, 1, start
, val
);
58 GP_SET_BITS1_ALIGNED(4, 1, start
, val
);
63 GP_SET_BITS1_ALIGNED(5, 1, start
, val
);
68 GP_SET_BITS1_ALIGNED(6, 1, start
, val
);
73 GP_SET_BITS1_ALIGNED(7, 1, start
, val
);
82 /* Write as many bytes as possible */
83 memset(start
, bytes_1BPP
[val
& 0x01], len
/8);
90 GP_SET_BITS1_ALIGNED(6, 1, start
, val
);
92 GP_SET_BITS1_ALIGNED(5, 1, start
, val
);
94 GP_SET_BITS1_ALIGNED(4, 1, start
, val
);
96 GP_SET_BITS1_ALIGNED(3, 1, start
, val
);
98 GP_SET_BITS1_ALIGNED(2, 1, start
, val
);
100 GP_SET_BITS1_ALIGNED(1, 1, start
, val
);
102 GP_SET_BITS1_ALIGNED(0, 1, start
, val
);
107 void GP_WritePixels_1BPP_BE(void *start
, uint8_t off
,
108 size_t cnt
, unsigned int val
)
112 /* Write start of the line */
117 GP_SET_BITS1_ALIGNED(6, 1, start
, val
);
122 GP_SET_BITS1_ALIGNED(5, 1, start
, val
);
127 GP_SET_BITS1_ALIGNED(4, 1, start
, val
);
132 GP_SET_BITS1_ALIGNED(3, 1, start
, val
);
137 GP_SET_BITS1_ALIGNED(2, 1, start
, val
);
142 GP_SET_BITS1_ALIGNED(1, 1, start
, val
);
147 GP_SET_BITS1_ALIGNED(0, 1, start
, val
);
156 /* Write as many bytes as possible */
157 memset(start
, bytes_1BPP
[val
& 0x01], len
/8);
164 GP_SET_BITS1_ALIGNED(1, 1, start
, val
);
166 GP_SET_BITS1_ALIGNED(2, 1, start
, val
);
168 GP_SET_BITS1_ALIGNED(3, 1, start
, val
);
170 GP_SET_BITS1_ALIGNED(4, 1, start
, val
);
172 GP_SET_BITS1_ALIGNED(5, 1, start
, val
);
174 GP_SET_BITS1_ALIGNED(6, 1, start
, val
);
176 GP_SET_BITS1_ALIGNED(7, 1, start
, val
);
181 static const uint8_t bytes_2BPP
[] = {0x00, 0x55, 0xaa, 0xff};
183 void GP_WritePixels_2BPP_LE(void *start
, uint8_t off
,
184 size_t cnt
, unsigned int val
)
188 /* Write start of the line */
193 GP_SET_BITS1_ALIGNED(2, 2, start
, val
);
198 GP_SET_BITS1_ALIGNED(4, 2, start
, val
);
203 GP_SET_BITS1_ALIGNED(6, 2, start
, val
);
212 /* Write as many bytes as possible */
213 memset(start
, bytes_2BPP
[val
& 0x03], len
/4);
220 GP_SET_BITS1_ALIGNED(4, 2, start
, val
);
222 GP_SET_BITS1_ALIGNED(2, 2, start
, val
);
224 GP_SET_BITS1_ALIGNED(0, 2, start
, val
);
229 void GP_WritePixels_2BPP_BE(void *start
, uint8_t off
,
230 size_t cnt
, unsigned int val
)
234 /* Write start of the line */
239 GP_SET_BITS1_ALIGNED(6, 2, start
, val
);
244 GP_SET_BITS1_ALIGNED(4, 2, start
, val
);
249 GP_SET_BITS1_ALIGNED(2, 2, start
, val
);
258 /* Write as many bytes as possible */
259 memset(start
, bytes_2BPP
[val
& 0x03], len
/4);
266 GP_SET_BITS1_ALIGNED(0, 2, start
, val
);
268 GP_SET_BITS1_ALIGNED(2, 2, start
, val
);
270 GP_SET_BITS1_ALIGNED(4, 2, start
, val
);
275 static const uint8_t bytes_4BPP
[] = {
276 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
277 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
280 void GP_WritePixels_4BPP_LE(void *start
, uint8_t off
,
281 size_t cnt
, unsigned int val
)
285 /* Write start of the line */
290 GP_SET_BITS1_ALIGNED(4, 4, start
, val
);
299 /* Write as many bytes as possible */
300 memset(start
, bytes_4BPP
[val
& 0x0f], len
/2);
307 GP_SET_BITS1_ALIGNED(0, 4, start
, val
);
312 void GP_WritePixels_4BPP_BE(void *start
, uint8_t off
,
313 size_t cnt
, unsigned int val
)
317 /* Write start of the line */
322 GP_SET_BITS1_ALIGNED(0, 4, start
, val
);
331 /* Write as many bytes as possible */
332 memset(start
, bytes_4BPP
[val
& 0x0f], len
/2);
339 GP_SET_BITS1_ALIGNED(4, 4, start
, val
);
344 void GP_WritePixels_8BPP(void *start
, size_t count
, unsigned int value
)
346 memset(start
, value
, count
);
349 void GP_WritePixels_16BPP(void *start
, size_t count
, unsigned int value
)
351 uint16_t *p
= (uint16_t *) start
;
354 /* Write as much pixels as possible in 4-pixel blocks. */
355 for (i
= count
; i
>= 4; p
+= 4, i
-= 4) {
362 /* Write the rest. */
374 void GP_WritePixels_24BPP(void *start
, size_t count
, unsigned int value
)
376 uint8_t *bytep
= (uint8_t *) start
;
381 /* How much bytes we are offset against the 32-bit boundary. */
382 int shift
= ((uintptr_t) bytep
) % 4;
385 * Pixels remaining to draw (one less than pixelcount because
386 * one incomplete pixel is drawn during the preparation phase.)
391 * Handle each color component separately.
392 * (Probably they are R, G, B but who knows.)
394 uint8_t a
= value
& 0xff;
395 uint8_t b
= (value
>> 8) & 0xff;
396 uint8_t c
= (value
>> 16) & 0xff;
402 * The line consists of three repeating 32-bit segments
403 * (except for the starting and ending segment:
407 uint32_t abca
= a
<< 24 | b
<< 16 | c
<< 8 | a
;
408 uint32_t bcab
= b
<< 24 | c
<< 16 | a
<< 8 | b
;
409 uint32_t cabc
= c
<< 24 | a
<< 16 | b
<< 8 | c
;
411 uint32_t abca
= a
<< 24 | c
<< 16 | b
<< 8 | a
;
412 uint32_t bcab
= b
<< 24 | a
<< 16 | c
<< 8 | b
;
413 uint32_t cabc
= c
<< 24 | b
<< 16 | a
<< 8 | c
;
417 * Handle the first few bytes (1 pixel or less) and prepare
418 * the repeating sequence.
421 default: /* shut up gcc */
426 p
= (uint32_t *) bytep
;
433 p
= (uint32_t *)(bytep
+ 1);
441 p
= (uint32_t *)(bytep
+ 2);
450 p
= (uint32_t *)(bytep
+ 3);
456 * Write as much of the line as possible as
457 * triplets of 32-bit numbers; hopefully the compiler can
458 * put some wide write instructions in.
468 /* Write the rest of the last pixel of the main part */
469 bytep
= (uint8_t *) p
;
497 void GP_WritePixels_32BPP(void *start
, size_t count
, unsigned int value
)
500 * Inspired by GNU libc's wmemset() (by Ulrich Drepper, licensed under LGPL).
502 * Write the pixels in groups of four, allowing the compiler to use
503 * MMX/SSE/similar instructions if available. The last few pixels are
504 * copied normally one-by-one. (Speed gain is about 15% over a naive loop
505 * on AMD Phenom CPU.)
508 uint32_t *p
= (uint32_t *) start
;