1 #include <stdbool.h>
2
3 #ifndef SNA_TRAPEZOIDS_H
4 #define SNA_TRAPEZOIDS_H
5
6 #define NO_ACCEL 0
7 #define FORCE_FALLBACK 0
8 #define NO_ALIGNED_BOXES 0
9 #define NO_UNALIGNED_BOXES 0
10 #define NO_SCAN_CONVERTER 0
11 #define NO_GPU_THREADS 0
12
13 #define NO_IMPRECISE 0
14 #define NO_PRECISE 0
15
16 #if 0
17 #define __DBG DBG
18 #else
19 #define __DBG(x)
20 #endif
21
22 bool
23 composite_aligned_boxes(struct sna *sna,
24 CARD8 op,
25 PicturePtr src,
26 PicturePtr dst,
27 PictFormatPtr maskFormat,
28 INT16 src_x, INT16 src_y,
29 int ntrap, const xTrapezoid *traps,
30 bool force_fallback);
31
32 bool
33 composite_unaligned_boxes(struct sna *sna,
34 CARD8 op,
35 PicturePtr src,
36 PicturePtr dst,
37 PictFormatPtr maskFormat,
38 INT16 src_x, INT16 src_y,
39 int ntrap, const xTrapezoid *traps,
40 bool force_fallback);
41
42 bool
43 mono_trapezoids_span_converter(struct sna *sna,
44 CARD8 op, PicturePtr src, PicturePtr dst,
45 INT16 src_x, INT16 src_y,
46 int ntrap, xTrapezoid *traps);
47
48 bool
49 mono_trapezoid_span_inplace(struct sna *sna,
50 CARD8 op,
51 PicturePtr src,
52 PicturePtr dst,
53 INT16 src_x, INT16 src_y,
54 int ntrap, xTrapezoid *traps);
55
56 bool
57 mono_triangles_span_converter(struct sna *sna,
58 CARD8 op, PicturePtr src, PicturePtr dst,
59 INT16 src_x, INT16 src_y,
60 int count, xTriangle *tri);
61
62 bool
63 imprecise_trapezoid_span_inplace(struct sna *sna,
64 CARD8 op, PicturePtr src, PicturePtr dst,
65 PictFormatPtr maskFormat, unsigned flags,
66 INT16 src_x, INT16 src_y,
67 int ntrap, xTrapezoid *traps,
68 bool fallback);
69
70 bool
71 imprecise_trapezoid_span_converter(struct sna *sna,
72 CARD8 op, PicturePtr src, PicturePtr dst,
73 PictFormatPtr maskFormat, unsigned int flags,
74 INT16 src_x, INT16 src_y,
75 int ntrap, xTrapezoid *traps);
76
77 bool
78 imprecise_trapezoid_mask_converter(CARD8 op, PicturePtr src, PicturePtr dst,
79 PictFormatPtr maskFormat, unsigned flags,
80 INT16 src_x, INT16 src_y,
81 int ntrap, xTrapezoid *traps);
82
83 bool
84 imprecise_trapezoid_span_fallback(CARD8 op, PicturePtr src, PicturePtr dst,
85 PictFormatPtr maskFormat, unsigned flags,
86 INT16 src_x, INT16 src_y,
87 int ntrap, xTrapezoid *traps);
88
89 bool
90 precise_trapezoid_span_inplace(struct sna *sna,
91 CARD8 op, PicturePtr src, PicturePtr dst,
92 PictFormatPtr maskFormat, unsigned flags,
93 INT16 src_x, INT16 src_y,
94 int ntrap, xTrapezoid *traps,
95 bool fallback);
96
97 bool
98 precise_trapezoid_span_converter(struct sna *sna,
99 CARD8 op, PicturePtr src, PicturePtr dst,
100 PictFormatPtr maskFormat, unsigned int flags,
101 INT16 src_x, INT16 src_y,
102 int ntrap, xTrapezoid *traps);
103
104 bool
105 precise_trapezoid_mask_converter(CARD8 op, PicturePtr src, PicturePtr dst,
106 PictFormatPtr maskFormat, unsigned flags,
107 INT16 src_x, INT16 src_y,
108 int ntrap, xTrapezoid *traps);
109
110 bool
111 precise_trapezoid_span_fallback(CARD8 op, PicturePtr src, PicturePtr dst,
112 PictFormatPtr maskFormat, unsigned flags,
113 INT16 src_x, INT16 src_y,
114 int ntrap, xTrapezoid *traps);
115
is_mono(PicturePtr dst,PictFormatPtr mask)116 static inline bool is_mono(PicturePtr dst, PictFormatPtr mask)
117 {
118 return mask ? mask->depth < 8 : dst->polyEdge==PolyEdgeSharp;
119 }
120
is_precise(PicturePtr dst,PictFormatPtr mask)121 static inline bool is_precise(PicturePtr dst, PictFormatPtr mask)
122 {
123 return dst->polyMode == PolyModePrecise && !is_mono(dst, mask);
124 }
125
126 static inline bool
trapezoid_span_inplace(struct sna * sna,CARD8 op,PicturePtr src,PicturePtr dst,PictFormatPtr maskFormat,unsigned flags,INT16 src_x,INT16 src_y,int ntrap,xTrapezoid * traps,bool fallback)127 trapezoid_span_inplace(struct sna *sna,
128 CARD8 op, PicturePtr src, PicturePtr dst,
129 PictFormatPtr maskFormat, unsigned flags,
130 INT16 src_x, INT16 src_y,
131 int ntrap, xTrapezoid *traps,
132 bool fallback)
133 {
134 if (NO_SCAN_CONVERTER)
135 return false;
136
137 if (dst->alphaMap) {
138 DBG(("%s: fallback -- dst alphamap\n",
139 __FUNCTION__));
140 return false;
141 }
142
143 if (!fallback && is_gpu(sna, dst->pDrawable, PREFER_GPU_SPANS)) {
144 DBG(("%s: fallback -- can not perform operation in place, destination busy\n",
145 __FUNCTION__));
146
147 return false;
148 }
149
150 if (is_mono(dst, maskFormat))
151 return mono_trapezoid_span_inplace(sna, op, src, dst, src_x, src_y, ntrap, traps);
152 else if (is_precise(dst, maskFormat))
153 return precise_trapezoid_span_inplace(sna, op, src, dst, maskFormat, flags, src_x, src_y, ntrap, traps, fallback);
154 else
155 return imprecise_trapezoid_span_inplace(sna, op, src, dst, maskFormat, flags, src_x, src_y, ntrap, traps, fallback);
156 }
157
158 static inline bool
trapezoid_span_converter(struct sna * sna,CARD8 op,PicturePtr src,PicturePtr dst,PictFormatPtr maskFormat,unsigned int flags,INT16 src_x,INT16 src_y,int ntrap,xTrapezoid * traps)159 trapezoid_span_converter(struct sna *sna,
160 CARD8 op, PicturePtr src, PicturePtr dst,
161 PictFormatPtr maskFormat, unsigned int flags,
162 INT16 src_x, INT16 src_y,
163 int ntrap, xTrapezoid *traps)
164 {
165 if (NO_SCAN_CONVERTER)
166 return false;
167
168 if (is_mono(dst, maskFormat))
169 return mono_trapezoids_span_converter(sna, op, src, dst, src_x, src_y, ntrap, traps);
170 else if (is_precise(dst, maskFormat))
171 return precise_trapezoid_span_converter(sna, op, src, dst, maskFormat, flags, src_x, src_y, ntrap, traps);
172 else
173 return imprecise_trapezoid_span_converter(sna, op, src, dst, maskFormat, flags, src_x, src_y, ntrap, traps);
174 }
175
176 static inline bool
trapezoid_mask_converter(CARD8 op,PicturePtr src,PicturePtr dst,PictFormatPtr maskFormat,unsigned flags,INT16 src_x,INT16 src_y,int ntrap,xTrapezoid * traps)177 trapezoid_mask_converter(CARD8 op, PicturePtr src, PicturePtr dst,
178 PictFormatPtr maskFormat, unsigned flags,
179 INT16 src_x, INT16 src_y,
180 int ntrap, xTrapezoid *traps)
181 {
182 if (NO_SCAN_CONVERTER)
183 return false;
184
185 if (is_precise(dst, maskFormat))
186 return precise_trapezoid_mask_converter(op, src, dst, maskFormat, flags, src_x, src_y, ntrap, traps);
187 else
188 return imprecise_trapezoid_mask_converter(op, src, dst, maskFormat, flags, src_x, src_y, ntrap, traps);
189 }
190
191 static inline bool
trapezoid_span_fallback(CARD8 op,PicturePtr src,PicturePtr dst,PictFormatPtr maskFormat,unsigned flags,INT16 src_x,INT16 src_y,int ntrap,xTrapezoid * traps)192 trapezoid_span_fallback(CARD8 op, PicturePtr src, PicturePtr dst,
193 PictFormatPtr maskFormat, unsigned flags,
194 INT16 src_x, INT16 src_y,
195 int ntrap, xTrapezoid *traps)
196 {
197 if (NO_SCAN_CONVERTER)
198 return false;
199
200 if (is_precise(dst, maskFormat))
201 return precise_trapezoid_span_fallback(op, src, dst, maskFormat, flags, src_x, src_y, ntrap, traps);
202 else
203 return imprecise_trapezoid_span_fallback(op, src, dst, maskFormat, flags, src_x, src_y, ntrap, traps);
204 }
205
206 bool
207 mono_trap_span_converter(struct sna *sna,
208 PicturePtr dst,
209 INT16 x, INT16 y,
210 int ntrap, xTrap *traps);
211
212 bool
213 precise_trap_span_converter(struct sna *sna,
214 PicturePtr dst,
215 INT16 src_x, INT16 src_y,
216 int ntrap, xTrap *trap);
217
218 bool
219 imprecise_trap_span_converter(struct sna *sna,
220 PicturePtr dst,
221 INT16 src_x, INT16 src_y,
222 int ntrap, xTrap *trap);
223
224 static inline bool
trap_span_converter(struct sna * sna,PicturePtr dst,INT16 src_x,INT16 src_y,int ntrap,xTrap * trap)225 trap_span_converter(struct sna *sna,
226 PicturePtr dst,
227 INT16 src_x, INT16 src_y,
228 int ntrap, xTrap *trap)
229 {
230 if (NO_SCAN_CONVERTER)
231 return false;
232
233 if (dst->polyEdge == PolyEdgeSharp || dst->pDrawable->depth < 8)
234 return mono_trap_span_converter(sna, dst, src_x, src_y, ntrap, trap);
235 else if (dst->polyMode == PolyModePrecise)
236 return precise_trap_span_converter(sna, dst, src_x, src_y, ntrap, trap);
237 else
238 return imprecise_trap_span_converter(sna, dst, src_x, src_y, ntrap, trap);
239 }
240
241 bool
242 trap_mask_converter(struct sna *sna,
243 PicturePtr picture,
244 INT16 x, INT16 y,
245 int ntrap, xTrap *trap);
246
247 bool
248 triangles_span_converter(struct sna *sna,
249 CARD8 op, PicturePtr src, PicturePtr dst,
250 PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
251 int count, xTriangle *tri);
252
253 bool
254 triangles_mask_converter(CARD8 op, PicturePtr src, PicturePtr dst,
255 PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
256 int count, xTriangle *tri);
257
258 bool
259 mono_tristrip_span_converter(struct sna *sna,
260 CARD8 op, PicturePtr src, PicturePtr dst,
261 INT16 src_x, INT16 src_y,
262 int count, xPointFixed *points);
263 bool
264 imprecise_tristrip_span_converter(struct sna *sna,
265 CARD8 op, PicturePtr src, PicturePtr dst,
266 PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
267 int count, xPointFixed *points);
268 bool
269 precise_tristrip_span_converter(struct sna *sna,
270 CARD8 op, PicturePtr src, PicturePtr dst,
271 PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
272 int count, xPointFixed *points);
273
274 static inline bool
tristrip_span_converter(struct sna * sna,CARD8 op,PicturePtr src,PicturePtr dst,PictFormatPtr maskFormat,INT16 src_x,INT16 src_y,int count,xPointFixed * points)275 tristrip_span_converter(struct sna *sna,
276 CARD8 op, PicturePtr src, PicturePtr dst,
277 PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
278 int count, xPointFixed *points)
279 {
280 if (NO_SCAN_CONVERTER)
281 return false;
282
283 if (is_mono(dst, maskFormat))
284 return mono_tristrip_span_converter(sna, op, src, dst, src_x, src_y, count, points);
285 else if (is_precise(dst, maskFormat))
286 return precise_tristrip_span_converter(sna, op, src, dst, maskFormat, src_x, src_y, count, points);
287 else
288 return imprecise_tristrip_span_converter(sna, op, src, dst, maskFormat, src_x, src_y, count, points);
289 }
290
trapezoid_origin(const xLineFixed * l,int16_t * x,int16_t * y)291 inline static void trapezoid_origin(const xLineFixed *l, int16_t *x, int16_t *y)
292 {
293 if (l->p1.y < l->p2.y) {
294 *x = pixman_fixed_to_int(l->p1.x);
295 *y = pixman_fixed_to_int(l->p1.y);
296 } else {
297 *x = pixman_fixed_to_int(l->p2.x);
298 *y = pixman_fixed_to_int(l->p2.y);
299 }
300 }
301
302 #define ONE_HALF 0x7f
303 #define RB_MASK 0x00ff00ff
304 #define RB_ONE_HALF 0x007f007f
305 #define RB_MASK_PLUS_ONE 0x01000100
306 #define G_SHIFT 8
307
308 static force_inline uint32_t
mul8x2_8(uint32_t a,uint8_t b)309 mul8x2_8 (uint32_t a, uint8_t b)
310 {
311 uint32_t t = (a & RB_MASK) * b + RB_ONE_HALF;
312 return ((t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT) & RB_MASK;
313 }
314
315 static force_inline uint32_t
add8x2_8x2(uint32_t a,uint32_t b)316 add8x2_8x2(uint32_t a, uint32_t b)
317 {
318 uint32_t t = a + b;
319 t |= RB_MASK_PLUS_ONE - ((t >> G_SHIFT) & RB_MASK);
320 return t & RB_MASK;
321 }
322
323 static force_inline uint32_t
lerp8x4(uint32_t src,uint8_t a,uint32_t dst)324 lerp8x4(uint32_t src, uint8_t a, uint32_t dst)
325 {
326 return (add8x2_8x2(mul8x2_8(src, a),
327 mul8x2_8(dst, ~a)) |
328 add8x2_8x2(mul8x2_8(src >> G_SHIFT, a),
329 mul8x2_8(dst >> G_SHIFT, ~a)) << G_SHIFT);
330 }
331
332 static force_inline uint8_t
mul_8_8(uint8_t a,uint8_t b)333 mul_8_8(uint8_t a, uint8_t b)
334 {
335 uint16_t t = a * (uint16_t)b + 0x7f;
336 return ((t >> 8) + t) >> 8;
337 }
338
multa(uint32_t s,uint8_t a,int shift)339 static inline uint32_t multa(uint32_t s, uint8_t a, int shift)
340 {
341 return mul_8_8((s >> shift) & 0xff, a) << shift;
342 }
343
mul_4x8_8(uint32_t color,uint8_t alpha)344 static inline uint32_t mul_4x8_8(uint32_t color, uint8_t alpha)
345 {
346 uint32_t v;
347
348 v = 0;
349 v |= multa(color, alpha, 24);
350 v |= multa(color, alpha, 16);
351 v |= multa(color, alpha, 8);
352 v |= multa(color, alpha, 0);
353
354 return v;
355 }
356
357 static inline bool
xTriangleValid(const xTriangle * t)358 xTriangleValid(const xTriangle *t)
359 {
360 xPointFixed v1, v2;
361
362 v1.x = t->p2.x - t->p1.x;
363 v1.y = t->p2.y - t->p1.y;
364
365 v2.x = t->p3.x - t->p1.x;
366 v2.y = t->p3.y - t->p1.y;
367
368 /* if the length of any edge is zero, the area must be zero */
369 if (v1.x == 0 && v1.y == 0)
370 return false;
371 if (v2.x == 0 && v2.y == 0)
372 return false;
373
374 /* if the cross-product is zero, so it the size */
375 return v2.y * v1.x != v1.y * v2.x;
376 }
377
378 #define SAMPLES_X 17
379 #define SAMPLES_Y 15
380
381 #define FAST_SAMPLES_shift 2
382 #define FAST_SAMPLES_X (1<<FAST_SAMPLES_shift)
383 #define FAST_SAMPLES_Y (1<<FAST_SAMPLES_shift)
384 #define FAST_SAMPLES_mask ((1<<FAST_SAMPLES_shift)-1)
385
386 #define pixman_fixed_integer_floor(V) pixman_fixed_to_int(V)
387 #define pixman_fixed_integer_ceil(V) pixman_fixed_to_int(pixman_fixed_ceil(V))
388
pixman_fixed_to_fast(pixman_fixed_t v)389 static inline int pixman_fixed_to_fast(pixman_fixed_t v)
390 {
391 return (v + (1<<(16-FAST_SAMPLES_shift-1))) >> (16 - FAST_SAMPLES_shift);
392 }
393
394 bool trapezoids_bounds(int n, const xTrapezoid *t, BoxPtr box);
395
396 #define TOR_INPLACE_SIZE 128
397
398 #endif /* SNA_TRAPEZOIDS_H */
399