142542f5fSchristos#include <stdbool.h>
242542f5fSchristos
342542f5fSchristos#ifndef SNA_TRAPEZOIDS_H
442542f5fSchristos#define SNA_TRAPEZOIDS_H
542542f5fSchristos
642542f5fSchristos#define NO_ACCEL 0
742542f5fSchristos#define FORCE_FALLBACK 0
842542f5fSchristos#define NO_ALIGNED_BOXES 0
942542f5fSchristos#define NO_UNALIGNED_BOXES 0
1042542f5fSchristos#define NO_SCAN_CONVERTER 0
1142542f5fSchristos#define NO_GPU_THREADS 0
1242542f5fSchristos
1342542f5fSchristos#define NO_IMPRECISE 0
1442542f5fSchristos#define NO_PRECISE 0
1542542f5fSchristos
1613496ba1Ssnj#if 0
1713496ba1Ssnj#define __DBG DBG
1813496ba1Ssnj#else
1913496ba1Ssnj#define __DBG(x)
2013496ba1Ssnj#endif
2113496ba1Ssnj
2242542f5fSchristosbool
2342542f5fSchristoscomposite_aligned_boxes(struct sna *sna,
2442542f5fSchristos			CARD8 op,
2542542f5fSchristos			PicturePtr src,
2642542f5fSchristos			PicturePtr dst,
2742542f5fSchristos			PictFormatPtr maskFormat,
2842542f5fSchristos			INT16 src_x, INT16 src_y,
2942542f5fSchristos			int ntrap, const xTrapezoid *traps,
3042542f5fSchristos			bool force_fallback);
3142542f5fSchristos
3242542f5fSchristosbool
3342542f5fSchristoscomposite_unaligned_boxes(struct sna *sna,
3442542f5fSchristos			  CARD8 op,
3542542f5fSchristos			  PicturePtr src,
3642542f5fSchristos			  PicturePtr dst,
3742542f5fSchristos			  PictFormatPtr maskFormat,
3842542f5fSchristos			  INT16 src_x, INT16 src_y,
3942542f5fSchristos			  int ntrap, const xTrapezoid *traps,
4042542f5fSchristos			  bool force_fallback);
4142542f5fSchristos
4242542f5fSchristosbool
4342542f5fSchristosmono_trapezoids_span_converter(struct sna *sna,
4442542f5fSchristos			       CARD8 op, PicturePtr src, PicturePtr dst,
4542542f5fSchristos			       INT16 src_x, INT16 src_y,
4642542f5fSchristos			       int ntrap, xTrapezoid *traps);
4742542f5fSchristos
4842542f5fSchristosbool
4942542f5fSchristosmono_trapezoid_span_inplace(struct sna *sna,
5042542f5fSchristos			    CARD8 op,
5142542f5fSchristos			    PicturePtr src,
5242542f5fSchristos			    PicturePtr dst,
5342542f5fSchristos			    INT16 src_x, INT16 src_y,
5442542f5fSchristos			    int ntrap, xTrapezoid *traps);
5542542f5fSchristos
5642542f5fSchristosbool
5742542f5fSchristosmono_triangles_span_converter(struct sna *sna,
5842542f5fSchristos			      CARD8 op, PicturePtr src, PicturePtr dst,
5942542f5fSchristos			      INT16 src_x, INT16 src_y,
6042542f5fSchristos			      int count, xTriangle *tri);
6142542f5fSchristos
6242542f5fSchristosbool
6342542f5fSchristosimprecise_trapezoid_span_inplace(struct sna *sna,
6442542f5fSchristos				 CARD8 op, PicturePtr src, PicturePtr dst,
6542542f5fSchristos				 PictFormatPtr maskFormat, unsigned flags,
6642542f5fSchristos				 INT16 src_x, INT16 src_y,
6742542f5fSchristos				 int ntrap, xTrapezoid *traps,
6842542f5fSchristos				 bool fallback);
6942542f5fSchristos
7042542f5fSchristosbool
7142542f5fSchristosimprecise_trapezoid_span_converter(struct sna *sna,
7242542f5fSchristos				   CARD8 op, PicturePtr src, PicturePtr dst,
7342542f5fSchristos				   PictFormatPtr maskFormat, unsigned int flags,
7442542f5fSchristos				   INT16 src_x, INT16 src_y,
7542542f5fSchristos				   int ntrap, xTrapezoid *traps);
7642542f5fSchristos
7742542f5fSchristosbool
7842542f5fSchristosimprecise_trapezoid_mask_converter(CARD8 op, PicturePtr src, PicturePtr dst,
7942542f5fSchristos				   PictFormatPtr maskFormat, unsigned flags,
8042542f5fSchristos				   INT16 src_x, INT16 src_y,
8142542f5fSchristos				   int ntrap, xTrapezoid *traps);
8242542f5fSchristos
8342542f5fSchristosbool
8442542f5fSchristosimprecise_trapezoid_span_fallback(CARD8 op, PicturePtr src, PicturePtr dst,
8542542f5fSchristos				  PictFormatPtr maskFormat, unsigned flags,
8642542f5fSchristos				  INT16 src_x, INT16 src_y,
8742542f5fSchristos				  int ntrap, xTrapezoid *traps);
8842542f5fSchristos
8942542f5fSchristosbool
9042542f5fSchristosprecise_trapezoid_span_inplace(struct sna *sna,
9142542f5fSchristos				 CARD8 op, PicturePtr src, PicturePtr dst,
9242542f5fSchristos				 PictFormatPtr maskFormat, unsigned flags,
9342542f5fSchristos				 INT16 src_x, INT16 src_y,
9442542f5fSchristos				 int ntrap, xTrapezoid *traps,
9542542f5fSchristos				 bool fallback);
9642542f5fSchristos
9742542f5fSchristosbool
9842542f5fSchristosprecise_trapezoid_span_converter(struct sna *sna,
9942542f5fSchristos				   CARD8 op, PicturePtr src, PicturePtr dst,
10042542f5fSchristos				   PictFormatPtr maskFormat, unsigned int flags,
10142542f5fSchristos				   INT16 src_x, INT16 src_y,
10242542f5fSchristos				   int ntrap, xTrapezoid *traps);
10342542f5fSchristos
10442542f5fSchristosbool
10542542f5fSchristosprecise_trapezoid_mask_converter(CARD8 op, PicturePtr src, PicturePtr dst,
10642542f5fSchristos				   PictFormatPtr maskFormat, unsigned flags,
10742542f5fSchristos				   INT16 src_x, INT16 src_y,
10842542f5fSchristos				   int ntrap, xTrapezoid *traps);
10942542f5fSchristos
11042542f5fSchristosbool
11142542f5fSchristosprecise_trapezoid_span_fallback(CARD8 op, PicturePtr src, PicturePtr dst,
11242542f5fSchristos				PictFormatPtr maskFormat, unsigned flags,
11342542f5fSchristos				INT16 src_x, INT16 src_y,
11442542f5fSchristos				int ntrap, xTrapezoid *traps);
11542542f5fSchristos
11642542f5fSchristosstatic inline bool is_mono(PicturePtr dst, PictFormatPtr mask)
11742542f5fSchristos{
11842542f5fSchristos	return mask ? mask->depth < 8 : dst->polyEdge==PolyEdgeSharp;
11942542f5fSchristos}
12042542f5fSchristos
12142542f5fSchristosstatic inline bool is_precise(PicturePtr dst, PictFormatPtr mask)
12242542f5fSchristos{
12342542f5fSchristos	return dst->polyMode == PolyModePrecise && !is_mono(dst, mask);
12442542f5fSchristos}
12542542f5fSchristos
12642542f5fSchristosstatic inline bool
12742542f5fSchristostrapezoid_span_inplace(struct sna *sna,
12842542f5fSchristos		       CARD8 op, PicturePtr src, PicturePtr dst,
12942542f5fSchristos		       PictFormatPtr maskFormat, unsigned flags,
13042542f5fSchristos		       INT16 src_x, INT16 src_y,
13142542f5fSchristos		       int ntrap, xTrapezoid *traps,
13242542f5fSchristos		       bool fallback)
13342542f5fSchristos{
13442542f5fSchristos	if (NO_SCAN_CONVERTER)
13542542f5fSchristos		return false;
13642542f5fSchristos
13742542f5fSchristos	if (dst->alphaMap) {
13842542f5fSchristos		DBG(("%s: fallback -- dst alphamap\n",
13942542f5fSchristos		     __FUNCTION__));
14042542f5fSchristos		return false;
14142542f5fSchristos	}
14242542f5fSchristos
14342542f5fSchristos	if (!fallback && is_gpu(sna, dst->pDrawable, PREFER_GPU_SPANS)) {
14442542f5fSchristos		DBG(("%s: fallback -- can not perform operation in place, destination busy\n",
14542542f5fSchristos		     __FUNCTION__));
14642542f5fSchristos
14742542f5fSchristos		return false;
14842542f5fSchristos	}
14942542f5fSchristos
15042542f5fSchristos	if (is_mono(dst, maskFormat))
15142542f5fSchristos		return mono_trapezoid_span_inplace(sna, op, src, dst, src_x, src_y, ntrap, traps);
15242542f5fSchristos	else if (is_precise(dst, maskFormat))
15342542f5fSchristos		return precise_trapezoid_span_inplace(sna, op, src, dst, maskFormat, flags, src_x, src_y, ntrap, traps, fallback);
15442542f5fSchristos	else
15542542f5fSchristos		return imprecise_trapezoid_span_inplace(sna, op, src, dst, maskFormat, flags, src_x, src_y, ntrap, traps, fallback);
15642542f5fSchristos}
15742542f5fSchristos
15842542f5fSchristosstatic inline bool
15942542f5fSchristostrapezoid_span_converter(struct sna *sna,
16042542f5fSchristos			 CARD8 op, PicturePtr src, PicturePtr dst,
16142542f5fSchristos			 PictFormatPtr maskFormat, unsigned int flags,
16242542f5fSchristos			 INT16 src_x, INT16 src_y,
16342542f5fSchristos			 int ntrap, xTrapezoid *traps)
16442542f5fSchristos{
16542542f5fSchristos	if (NO_SCAN_CONVERTER)
16642542f5fSchristos		return false;
16742542f5fSchristos
16842542f5fSchristos	if (is_mono(dst, maskFormat))
16942542f5fSchristos		return mono_trapezoids_span_converter(sna, op, src, dst, src_x, src_y, ntrap, traps);
17042542f5fSchristos	else if (is_precise(dst, maskFormat))
17142542f5fSchristos		return precise_trapezoid_span_converter(sna, op, src, dst, maskFormat, flags, src_x, src_y, ntrap, traps);
17242542f5fSchristos	else
17342542f5fSchristos		return imprecise_trapezoid_span_converter(sna, op, src, dst, maskFormat, flags, src_x, src_y, ntrap, traps);
17442542f5fSchristos}
17542542f5fSchristos
17642542f5fSchristosstatic inline bool
17742542f5fSchristostrapezoid_mask_converter(CARD8 op, PicturePtr src, PicturePtr dst,
17842542f5fSchristos			 PictFormatPtr maskFormat, unsigned flags,
17942542f5fSchristos			 INT16 src_x, INT16 src_y,
18042542f5fSchristos			 int ntrap, xTrapezoid *traps)
18142542f5fSchristos{
18242542f5fSchristos	if (NO_SCAN_CONVERTER)
18342542f5fSchristos		return false;
18442542f5fSchristos
18542542f5fSchristos	if (is_precise(dst, maskFormat))
18642542f5fSchristos		return precise_trapezoid_mask_converter(op, src, dst, maskFormat, flags, src_x, src_y, ntrap, traps);
18742542f5fSchristos	else
18842542f5fSchristos		return imprecise_trapezoid_mask_converter(op, src, dst, maskFormat, flags, src_x, src_y, ntrap, traps);
18942542f5fSchristos}
19042542f5fSchristos
19142542f5fSchristosstatic inline bool
19242542f5fSchristostrapezoid_span_fallback(CARD8 op, PicturePtr src, PicturePtr dst,
19342542f5fSchristos			PictFormatPtr maskFormat, unsigned flags,
19442542f5fSchristos			INT16 src_x, INT16 src_y,
19542542f5fSchristos			int ntrap, xTrapezoid *traps)
19642542f5fSchristos{
19742542f5fSchristos	if (NO_SCAN_CONVERTER)
19842542f5fSchristos		return false;
19942542f5fSchristos
20042542f5fSchristos	if (is_precise(dst, maskFormat))
20142542f5fSchristos		return precise_trapezoid_span_fallback(op, src, dst, maskFormat, flags, src_x, src_y, ntrap, traps);
20242542f5fSchristos	else
20342542f5fSchristos		return imprecise_trapezoid_span_fallback(op, src, dst, maskFormat, flags, src_x, src_y, ntrap, traps);
20442542f5fSchristos}
20542542f5fSchristos
20642542f5fSchristosbool
20713496ba1Ssnjmono_trap_span_converter(struct sna *sna,
20813496ba1Ssnj			 PicturePtr dst,
20913496ba1Ssnj			 INT16 x, INT16 y,
21013496ba1Ssnj			 int ntrap, xTrap *traps);
21113496ba1Ssnj
21213496ba1Ssnjbool
21313496ba1Ssnjprecise_trap_span_converter(struct sna *sna,
21413496ba1Ssnj			    PicturePtr dst,
21513496ba1Ssnj			    INT16 src_x, INT16 src_y,
21613496ba1Ssnj			    int ntrap, xTrap *trap);
21713496ba1Ssnj
21813496ba1Ssnjbool
21913496ba1Ssnjimprecise_trap_span_converter(struct sna *sna,
22013496ba1Ssnj			      PicturePtr dst,
22113496ba1Ssnj			      INT16 src_x, INT16 src_y,
22213496ba1Ssnj			      int ntrap, xTrap *trap);
22313496ba1Ssnj
22413496ba1Ssnjstatic inline bool
22542542f5fSchristostrap_span_converter(struct sna *sna,
22642542f5fSchristos		    PicturePtr dst,
22742542f5fSchristos		    INT16 src_x, INT16 src_y,
22813496ba1Ssnj		    int ntrap, xTrap *trap)
22913496ba1Ssnj{
23013496ba1Ssnj	if (NO_SCAN_CONVERTER)
23113496ba1Ssnj		return false;
23213496ba1Ssnj
23313496ba1Ssnj	if (dst->polyEdge == PolyEdgeSharp || dst->pDrawable->depth < 8)
23413496ba1Ssnj		return mono_trap_span_converter(sna, dst, src_x, src_y, ntrap, trap);
23513496ba1Ssnj	else if (dst->polyMode == PolyModePrecise)
23613496ba1Ssnj		return precise_trap_span_converter(sna, dst, src_x, src_y, ntrap, trap);
23713496ba1Ssnj	else
23813496ba1Ssnj		return imprecise_trap_span_converter(sna, dst, src_x, src_y, ntrap, trap);
23913496ba1Ssnj}
24042542f5fSchristos
24142542f5fSchristosbool
24242542f5fSchristostrap_mask_converter(struct sna *sna,
24342542f5fSchristos		    PicturePtr picture,
24442542f5fSchristos		    INT16 x, INT16 y,
24542542f5fSchristos		    int ntrap, xTrap *trap);
24642542f5fSchristos
24742542f5fSchristosbool
24842542f5fSchristostriangles_span_converter(struct sna *sna,
24942542f5fSchristos			 CARD8 op, PicturePtr src, PicturePtr dst,
25042542f5fSchristos			 PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
25142542f5fSchristos			 int count, xTriangle *tri);
25242542f5fSchristos
25342542f5fSchristosbool
25442542f5fSchristostriangles_mask_converter(CARD8 op, PicturePtr src, PicturePtr dst,
25542542f5fSchristos			 PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
25642542f5fSchristos			 int count, xTriangle *tri);
25742542f5fSchristos
25842542f5fSchristosbool
25913496ba1Ssnjmono_tristrip_span_converter(struct sna *sna,
26013496ba1Ssnj			     CARD8 op, PicturePtr src, PicturePtr dst,
26113496ba1Ssnj			     INT16 src_x, INT16 src_y,
26213496ba1Ssnj			     int count, xPointFixed *points);
26313496ba1Ssnjbool
26413496ba1Ssnjimprecise_tristrip_span_converter(struct sna *sna,
26513496ba1Ssnj				  CARD8 op, PicturePtr src, PicturePtr dst,
26613496ba1Ssnj				  PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
26713496ba1Ssnj				  int count, xPointFixed *points);
26813496ba1Ssnjbool
26913496ba1Ssnjprecise_tristrip_span_converter(struct sna *sna,
27013496ba1Ssnj				CARD8 op, PicturePtr src, PicturePtr dst,
27113496ba1Ssnj				PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
27213496ba1Ssnj				int count, xPointFixed *points);
27313496ba1Ssnj
27413496ba1Ssnjstatic inline bool
27542542f5fSchristostristrip_span_converter(struct sna *sna,
27642542f5fSchristos			CARD8 op, PicturePtr src, PicturePtr dst,
27742542f5fSchristos			PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
27813496ba1Ssnj			int count, xPointFixed *points)
27913496ba1Ssnj{
28013496ba1Ssnj	if (NO_SCAN_CONVERTER)
28113496ba1Ssnj		return false;
28213496ba1Ssnj
28313496ba1Ssnj	if (is_mono(dst, maskFormat))
28413496ba1Ssnj		return mono_tristrip_span_converter(sna, op, src, dst, src_x, src_y, count, points);
28513496ba1Ssnj	else if (is_precise(dst, maskFormat))
28613496ba1Ssnj		return precise_tristrip_span_converter(sna, op, src, dst, maskFormat, src_x, src_y, count, points);
28713496ba1Ssnj	else
28813496ba1Ssnj		return imprecise_tristrip_span_converter(sna, op, src, dst, maskFormat, src_x, src_y, count, points);
28913496ba1Ssnj}
29042542f5fSchristos
29142542f5fSchristosinline static void trapezoid_origin(const xLineFixed *l, int16_t *x, int16_t *y)
29242542f5fSchristos{
29342542f5fSchristos	if (l->p1.y < l->p2.y) {
29442542f5fSchristos		*x = pixman_fixed_to_int(l->p1.x);
29542542f5fSchristos		*y = pixman_fixed_to_int(l->p1.y);
29642542f5fSchristos	} else {
29742542f5fSchristos		*x = pixman_fixed_to_int(l->p2.x);
29842542f5fSchristos		*y = pixman_fixed_to_int(l->p2.y);
29942542f5fSchristos	}
30042542f5fSchristos}
30142542f5fSchristos
30242542f5fSchristos#define ONE_HALF 0x7f
30342542f5fSchristos#define RB_MASK 0x00ff00ff
30442542f5fSchristos#define RB_ONE_HALF 0x007f007f
30542542f5fSchristos#define RB_MASK_PLUS_ONE 0x01000100
30642542f5fSchristos#define G_SHIFT 8
30742542f5fSchristos
30842542f5fSchristosstatic force_inline uint32_t
30942542f5fSchristosmul8x2_8 (uint32_t a, uint8_t b)
31042542f5fSchristos{
31142542f5fSchristos	uint32_t t = (a & RB_MASK) * b + RB_ONE_HALF;
31242542f5fSchristos	return ((t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT) & RB_MASK;
31342542f5fSchristos}
31442542f5fSchristos
31542542f5fSchristosstatic force_inline uint32_t
31642542f5fSchristosadd8x2_8x2(uint32_t a, uint32_t b)
31742542f5fSchristos{
31842542f5fSchristos	uint32_t t = a + b;
31942542f5fSchristos	t |= RB_MASK_PLUS_ONE - ((t >> G_SHIFT) & RB_MASK);
32042542f5fSchristos	return t & RB_MASK;
32142542f5fSchristos}
32242542f5fSchristos
32342542f5fSchristosstatic force_inline uint32_t
32442542f5fSchristoslerp8x4(uint32_t src, uint8_t a, uint32_t dst)
32542542f5fSchristos{
32642542f5fSchristos	return (add8x2_8x2(mul8x2_8(src, a),
32742542f5fSchristos			   mul8x2_8(dst, ~a)) |
32842542f5fSchristos		add8x2_8x2(mul8x2_8(src >> G_SHIFT, a),
32942542f5fSchristos			   mul8x2_8(dst >> G_SHIFT, ~a)) << G_SHIFT);
33042542f5fSchristos}
33142542f5fSchristos
33242542f5fSchristosstatic force_inline uint8_t
33342542f5fSchristosmul_8_8(uint8_t a, uint8_t b)
33442542f5fSchristos{
33542542f5fSchristos    uint16_t t = a * (uint16_t)b + 0x7f;
33642542f5fSchristos    return ((t >> 8) + t) >> 8;
33742542f5fSchristos}
33842542f5fSchristos
33942542f5fSchristosstatic inline uint32_t multa(uint32_t s, uint8_t a, int shift)
34042542f5fSchristos{
34142542f5fSchristos	return mul_8_8((s >> shift) & 0xff, a) << shift;
34242542f5fSchristos}
34342542f5fSchristos
34442542f5fSchristosstatic inline uint32_t mul_4x8_8(uint32_t color, uint8_t alpha)
34542542f5fSchristos{
34642542f5fSchristos	uint32_t v;
34742542f5fSchristos
34842542f5fSchristos	v = 0;
34942542f5fSchristos	v |= multa(color, alpha, 24);
35042542f5fSchristos	v |= multa(color, alpha, 16);
35142542f5fSchristos	v |= multa(color, alpha, 8);
35242542f5fSchristos	v |= multa(color, alpha, 0);
35342542f5fSchristos
35442542f5fSchristos	return v;
35542542f5fSchristos}
35642542f5fSchristos
35742542f5fSchristosstatic inline bool
35842542f5fSchristosxTriangleValid(const xTriangle *t)
35942542f5fSchristos{
36042542f5fSchristos	xPointFixed v1, v2;
36142542f5fSchristos
36242542f5fSchristos	v1.x = t->p2.x - t->p1.x;
36342542f5fSchristos	v1.y = t->p2.y - t->p1.y;
36442542f5fSchristos
36542542f5fSchristos	v2.x = t->p3.x - t->p1.x;
36642542f5fSchristos	v2.y = t->p3.y - t->p1.y;
36742542f5fSchristos
36842542f5fSchristos	/* if the length of any edge is zero, the area must be zero */
36942542f5fSchristos	if (v1.x == 0 && v1.y == 0)
37042542f5fSchristos		return false;
37142542f5fSchristos	if (v2.x == 0 && v2.y == 0)
37242542f5fSchristos		return false;
37342542f5fSchristos
37442542f5fSchristos	/* if the cross-product is zero, so it the size */
37542542f5fSchristos	return v2.y * v1.x != v1.y * v2.x;
37642542f5fSchristos}
37742542f5fSchristos
37842542f5fSchristos#define SAMPLES_X 17
37942542f5fSchristos#define SAMPLES_Y 15
38042542f5fSchristos
38142542f5fSchristos#define FAST_SAMPLES_shift 2
38242542f5fSchristos#define FAST_SAMPLES_X (1<<FAST_SAMPLES_shift)
38342542f5fSchristos#define FAST_SAMPLES_Y (1<<FAST_SAMPLES_shift)
38442542f5fSchristos#define FAST_SAMPLES_mask ((1<<FAST_SAMPLES_shift)-1)
38542542f5fSchristos
38642542f5fSchristos#define pixman_fixed_integer_floor(V) pixman_fixed_to_int(V)
38742542f5fSchristos#define pixman_fixed_integer_ceil(V) pixman_fixed_to_int(pixman_fixed_ceil(V))
38842542f5fSchristos
38942542f5fSchristosstatic inline int pixman_fixed_to_fast(pixman_fixed_t v)
39042542f5fSchristos{
39113496ba1Ssnj	return (v + (1<<(16-FAST_SAMPLES_shift-1))) >> (16 - FAST_SAMPLES_shift);
39242542f5fSchristos}
39342542f5fSchristos
39442542f5fSchristosbool trapezoids_bounds(int n, const xTrapezoid *t, BoxPtr box);
39542542f5fSchristos
39642542f5fSchristos#define TOR_INPLACE_SIZE 128
39742542f5fSchristos
39842542f5fSchristos#endif /* SNA_TRAPEZOIDS_H */
399