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