summaryrefslogtreecommitdiffstats
path: root/gfx/cairo/libpixman/src/pixman-combine16.c
blob: 9ba439fe5bc63bf314933b63478e7d957b1eac83 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <math.h>
#include <string.h>

#include "pixman-private.h"

#include "pixman-combine32.h"

static force_inline uint32_t
combine_mask (const uint32_t src, const uint32_t mask)
{
    uint32_t s, m;

    m = mask >> A_SHIFT;

    if (!m)
	return 0;
    s = src;

    UN8x4_MUL_UN8 (s, m);

    return s;
}

static void
combine_src_u (pixman_implementation_t *imp,
               pixman_op_t              op,
               uint32_t *               dest,
               const uint32_t *         src,
               const uint32_t *         mask,
               int                      width)
{
    int i;

    if (!mask)
	memcpy (dest, src, width * sizeof (uint16_t));
    else
    {
	uint16_t *d = (uint16_t*)dest;
	uint16_t *src16 = (uint16_t*)src;
	for (i = 0; i < width; ++i)
	{
	    if ((*mask & 0xff000000) == 0xff000000) {
		// it's likely worth special casing
		// fully opaque because it avoids
		// the cost of conversion as well the multiplication
		*(d + i) = *src16;
	    } else {
		// the mask is still 32bits
		uint32_t s = combine_mask (convert_0565_to_8888(*src16), *mask);
		*(d + i) = convert_8888_to_0565(s);
	    }
	    mask++;
	    src16++;
	}
    }

}

static void
combine_over_u (pixman_implementation_t *imp,
               pixman_op_t              op,
               uint32_t *                dest,
               const uint32_t *          src,
               const uint32_t *          mask,
               int                      width)
{
    int i;

    if (!mask)
	memcpy (dest, src, width * sizeof (uint16_t));
    else
    {
	uint16_t *d = (uint16_t*)dest;
	uint16_t *src16 = (uint16_t*)src;
	for (i = 0; i < width; ++i)
	{
	    if ((*mask & 0xff000000) == 0xff000000) {
		// it's likely worth special casing
		// fully opaque because it avoids
		// the cost of conversion as well the multiplication
		*(d + i) = *src16;
	    } else if ((*mask & 0xff000000) == 0x00000000) {
		// keep the dest the same
	    } else {
		// the mask is still 32bits
		uint32_t s = combine_mask (convert_0565_to_8888(*src16), *mask);
		uint32_t ia = ALPHA_8 (~s);
		uint32_t d32 = convert_0565_to_8888(*(d + i));
		UN8x4_MUL_UN8_ADD_UN8x4 (d32, ia, s);
		*(d + i) = convert_8888_to_0565(d32);
	    }
	    mask++;
	    src16++;
	}
    }

}


void
_pixman_setup_combiner_functions_16 (pixman_implementation_t *imp)
{
    int i;
    for (i = 0; i < PIXMAN_N_OPERATORS; i++) {
	imp->combine_16[i] = NULL;
    }
    imp->combine_16[PIXMAN_OP_SRC] = combine_src_u;
    imp->combine_16[PIXMAN_OP_OVER] = combine_over_u;
}