1 /* WARNING: This file is generated by combine.pl from combine.inc.
2    Please edit one of those files rather than this one. */
3 
4 #line 1 "pixman-combine.c.template"
5 
6 #define COMPONENT_SIZE 16
7 #define MASK 0xffffULL
8 #define ONE_HALF 0x8000ULL
9 
10 #define A_SHIFT 16 * 3
11 #define R_SHIFT 16 * 2
12 #define G_SHIFT 16
13 #define A_MASK 0xffff000000000000ULL
14 #define R_MASK 0xffff00000000ULL
15 #define G_MASK 0xffff0000ULL
16 
17 #define RB_MASK 0xffff0000ffffULL
18 #define AG_MASK 0xffff0000ffff0000ULL
19 #define RB_ONE_HALF 0x800000008000ULL
20 #define RB_MASK_PLUS_ONE 0x10000000010000ULL
21 
22 #define ALPHA_16(x) ((x) >> A_SHIFT)
23 #define RED_16(x) (((x) >> R_SHIFT) & MASK)
24 #define GREEN_16(x) (((x) >> G_SHIFT) & MASK)
25 #define BLUE_16(x) ((x) & MASK)
26 
27 /*
28  * Helper macros.
29  */
30 
31 #define MUL_UN16(a, b, t)						\
32     ((t) = (a) * (uint32_t)(b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT ))
33 
34 #define DIV_UN16(a, b)							\
35     (((uint32_t) (a) * MASK + ((b) / 2)) / (b))
36 
37 #define ADD_UN16(x, y, t)				     \
38     ((t) = (x) + (y),					     \
39      (uint64_t) (uint16_t) ((t) | (0 - ((t) >> G_SHIFT))))
40 
41 #define DIV_ONE_UN16(x)							\
42     (((x) + ONE_HALF + (((x) + ONE_HALF) >> G_SHIFT)) >> G_SHIFT)
43 
44 /*
45  * The methods below use some tricks to be able to do two color
46  * components at the same time.
47  */
48 
49 /*
50  * x_rb = (x_rb * a) / 255
51  */
52 #define UN16_rb_MUL_UN16(x, a, t)						\
53     do									\
54     {									\
55 	t  = ((x) & RB_MASK) * (a);					\
56 	t += RB_ONE_HALF;						\
57 	x = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT;		\
58 	x &= RB_MASK;							\
59     } while (0)
60 
61 /*
62  * x_rb = min (x_rb + y_rb, 255)
63  */
64 #define UN16_rb_ADD_UN16_rb(x, y, t)					\
65     do									\
66     {									\
67 	t = ((x) + (y));						\
68 	t |= RB_MASK_PLUS_ONE - ((t >> G_SHIFT) & RB_MASK);		\
69 	x = (t & RB_MASK);						\
70     } while (0)
71 
72 /*
73  * x_rb = (x_rb * a_rb) / 255
74  */
75 #define UN16_rb_MUL_UN16_rb(x, a, t)					\
76     do									\
77     {									\
78 	t  = (x & MASK) * (a & MASK);					\
79 	t |= (x & R_MASK) * ((a >> R_SHIFT) & MASK);			\
80 	t += RB_ONE_HALF;						\
81 	t = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT;		\
82 	x = t & RB_MASK;						\
83     } while (0)
84 
85 /*
86  * x_c = (x_c * a) / 255
87  */
88 #define UN16x4_MUL_UN16(x, a)						\
89     do									\
90     {									\
91 	uint64_t r1__, r2__, t__;					\
92 									\
93 	r1__ = (x);							\
94 	UN16_rb_MUL_UN16 (r1__, (a), t__);				\
95 									\
96 	r2__ = (x) >> G_SHIFT;						\
97 	UN16_rb_MUL_UN16 (r2__, (a), t__);				\
98 									\
99 	(x) = r1__ | (r2__ << G_SHIFT);					\
100     } while (0)
101 
102 /*
103  * x_c = (x_c * a) / 255 + y_c
104  */
105 #define UN16x4_MUL_UN16_ADD_UN16x4(x, a, y)				\
106     do									\
107     {									\
108 	uint64_t r1__, r2__, r3__, t__;					\
109 									\
110 	r1__ = (x);							\
111 	r2__ = (y) & RB_MASK;						\
112 	UN16_rb_MUL_UN16 (r1__, (a), t__);				\
113 	UN16_rb_ADD_UN16_rb (r1__, r2__, t__);				\
114 									\
115 	r2__ = (x) >> G_SHIFT;						\
116 	r3__ = ((y) >> G_SHIFT) & RB_MASK;				\
117 	UN16_rb_MUL_UN16 (r2__, (a), t__);				\
118 	UN16_rb_ADD_UN16_rb (r2__, r3__, t__);				\
119 									\
120 	(x) = r1__ | (r2__ << G_SHIFT);					\
121     } while (0)
122 
123 /*
124  * x_c = (x_c * a + y_c * b) / 255
125  */
126 #define UN16x4_MUL_UN16_ADD_UN16x4_MUL_UN16(x, a, y, b)			\
127     do									\
128     {									\
129 	uint64_t r1__, r2__, r3__, t__;					\
130 									\
131 	r1__ = (x);							\
132 	r2__ = (y);							\
133 	UN16_rb_MUL_UN16 (r1__, (a), t__);				\
134 	UN16_rb_MUL_UN16 (r2__, (b), t__);				\
135 	UN16_rb_ADD_UN16_rb (r1__, r2__, t__);				\
136 									\
137 	r2__ = ((x) >> G_SHIFT);					\
138 	r3__ = ((y) >> G_SHIFT);					\
139 	UN16_rb_MUL_UN16 (r2__, (a), t__);				\
140 	UN16_rb_MUL_UN16 (r3__, (b), t__);				\
141 	UN16_rb_ADD_UN16_rb (r2__, r3__, t__);				\
142 									\
143 	(x) = r1__ | (r2__ << G_SHIFT);					\
144     } while (0)
145 
146 /*
147  * x_c = (x_c * a_c) / 255
148  */
149 #define UN16x4_MUL_UN16x4(x, a)						\
150     do									\
151     {									\
152 	uint64_t r1__, r2__, r3__, t__;					\
153 									\
154 	r1__ = (x);							\
155 	r2__ = (a);							\
156 	UN16_rb_MUL_UN16_rb (r1__, r2__, t__);				\
157 									\
158 	r2__ = (x) >> G_SHIFT;						\
159 	r3__ = (a) >> G_SHIFT;						\
160 	UN16_rb_MUL_UN16_rb (r2__, r3__, t__);				\
161 									\
162 	(x) = r1__ | (r2__ << G_SHIFT);					\
163     } while (0)
164 
165 /*
166  * x_c = (x_c * a_c) / 255 + y_c
167  */
168 #define UN16x4_MUL_UN16x4_ADD_UN16x4(x, a, y)				\
169     do									\
170     {									\
171 	uint64_t r1__, r2__, r3__, t__;					\
172 									\
173 	r1__ = (x);							\
174 	r2__ = (a);							\
175 	UN16_rb_MUL_UN16_rb (r1__, r2__, t__);				\
176 	r2__ = (y) & RB_MASK;						\
177 	UN16_rb_ADD_UN16_rb (r1__, r2__, t__);				\
178 									\
179 	r2__ = ((x) >> G_SHIFT);					\
180 	r3__ = ((a) >> G_SHIFT);					\
181 	UN16_rb_MUL_UN16_rb (r2__, r3__, t__);				\
182 	r3__ = ((y) >> G_SHIFT) & RB_MASK;				\
183 	UN16_rb_ADD_UN16_rb (r2__, r3__, t__);				\
184 									\
185 	(x) = r1__ | (r2__ << G_SHIFT);					\
186     } while (0)
187 
188 /*
189  * x_c = (x_c * a_c + y_c * b) / 255
190  */
191 #define UN16x4_MUL_UN16x4_ADD_UN16x4_MUL_UN16(x, a, y, b)			\
192     do									\
193     {									\
194 	uint64_t r1__, r2__, r3__, t__;					\
195 									\
196 	r1__ = (x);							\
197 	r2__ = (a);							\
198 	UN16_rb_MUL_UN16_rb (r1__, r2__, t__);				\
199 	r2__ = (y);							\
200 	UN16_rb_MUL_UN16 (r2__, (b), t__);				\
201 	UN16_rb_ADD_UN16_rb (r1__, r2__, t__);				\
202 									\
203 	r2__ = (x) >> G_SHIFT;						\
204 	r3__ = (a) >> G_SHIFT;						\
205 	UN16_rb_MUL_UN16_rb (r2__, r3__, t__);				\
206 	r3__ = (y) >> G_SHIFT;						\
207 	UN16_rb_MUL_UN16 (r3__, (b), t__);				\
208 	UN16_rb_ADD_UN16_rb (r2__, r3__, t__);				\
209 									\
210 	x = r1__ | (r2__ << G_SHIFT);					\
211     } while (0)
212 
213 /*
214   x_c = min(x_c + y_c, 255)
215 */
216 #define UN16x4_ADD_UN16x4(x, y)						\
217     do									\
218     {									\
219 	uint64_t r1__, r2__, r3__, t__;					\
220 									\
221 	r1__ = (x) & RB_MASK;						\
222 	r2__ = (y) & RB_MASK;						\
223 	UN16_rb_ADD_UN16_rb (r1__, r2__, t__);				\
224 									\
225 	r2__ = ((x) >> G_SHIFT) & RB_MASK;				\
226 	r3__ = ((y) >> G_SHIFT) & RB_MASK;				\
227 	UN16_rb_ADD_UN16_rb (r2__, r3__, t__);				\
228 									\
229 	x = r1__ | (r2__ << G_SHIFT);					\
230     } while (0)
231