sna_trapezoids.h revision 428d7b3d
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
22bool
23composite_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
32bool
33composite_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
42bool
43mono_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
48bool
49mono_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
56bool
57mono_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
62bool
63imprecise_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
70bool
71imprecise_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
77bool
78imprecise_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
83bool
84imprecise_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
89bool
90precise_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
97bool
98precise_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
104bool
105precise_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
110bool
111precise_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
116static inline bool is_mono(PicturePtr dst, PictFormatPtr mask)
117{
118	return mask ? mask->depth < 8 : dst->polyEdge==PolyEdgeSharp;
119}
120
121static inline bool is_precise(PicturePtr dst, PictFormatPtr mask)
122{
123	return dst->polyMode == PolyModePrecise && !is_mono(dst, mask);
124}
125
126static inline bool
127trapezoid_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
158static inline bool
159trapezoid_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
176static inline bool
177trapezoid_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
191static inline bool
192trapezoid_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
206bool
207mono_trap_span_converter(struct sna *sna,
208			 PicturePtr dst,
209			 INT16 x, INT16 y,
210			 int ntrap, xTrap *traps);
211
212bool
213precise_trap_span_converter(struct sna *sna,
214			    PicturePtr dst,
215			    INT16 src_x, INT16 src_y,
216			    int ntrap, xTrap *trap);
217
218bool
219imprecise_trap_span_converter(struct sna *sna,
220			      PicturePtr dst,
221			      INT16 src_x, INT16 src_y,
222			      int ntrap, xTrap *trap);
223
224static inline bool
225trap_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
241bool
242trap_mask_converter(struct sna *sna,
243		    PicturePtr picture,
244		    INT16 x, INT16 y,
245		    int ntrap, xTrap *trap);
246
247bool
248triangles_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
253bool
254triangles_mask_converter(CARD8 op, PicturePtr src, PicturePtr dst,
255			 PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
256			 int count, xTriangle *tri);
257
258bool
259mono_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);
263bool
264imprecise_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);
268bool
269precise_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
274static inline bool
275tristrip_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
291inline 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
308static force_inline uint32_t
309mul8x2_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
315static force_inline uint32_t
316add8x2_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
323static force_inline uint32_t
324lerp8x4(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
332static force_inline uint8_t
333mul_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
339static 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
344static 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
357static inline bool
358xTriangleValid(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
389static 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
394bool trapezoids_bounds(int n, const xTrapezoid *t, BoxPtr box);
395
396#define TOR_INPLACE_SIZE 128
397
398#endif /* SNA_TRAPEZOIDS_H */
399