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