aboutsummaryrefslogtreecommitdiff
path: root/pixman
diff options
context:
space:
mode:
Diffstat (limited to 'pixman')
-rw-r--r--pixman/pixman/pixman-combine32.c58
-rw-r--r--pixman/test/utils-prng.c12
2 files changed, 63 insertions, 7 deletions
diff --git a/pixman/pixman/pixman-combine32.c b/pixman/pixman/pixman-combine32.c
index 54cc8771b..3ac7576bd 100644
--- a/pixman/pixman/pixman-combine32.c
+++ b/pixman/pixman/pixman-combine32.c
@@ -196,14 +196,58 @@ combine_over_u (pixman_implementation_t *imp,
{
int i;
- for (i = 0; i < width; ++i)
+ if (!mask)
{
- uint32_t s = combine_mask (src, mask, i);
- uint32_t d = *(dest + i);
- uint32_t ia = ALPHA_8 (~s);
-
- UN8x4_MUL_UN8_ADD_UN8x4 (d, ia, s);
- *(dest + i) = d;
+ for (i = 0; i < width; ++i)
+ {
+ uint32_t s = *(src + i);
+ uint32_t a = ALPHA_8 (s);
+ if (a == 0xFF)
+ {
+ *(dest + i) = s;
+ }
+ else if (s)
+ {
+ uint32_t d = *(dest + i);
+ uint32_t ia = a ^ 0xFF;
+ UN8x4_MUL_UN8_ADD_UN8x4 (d, ia, s);
+ *(dest + i) = d;
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < width; ++i)
+ {
+ uint32_t m = ALPHA_8 (*(mask + i));
+ if (m == 0xFF)
+ {
+ uint32_t s = *(src + i);
+ uint32_t a = ALPHA_8 (s);
+ if (a == 0xFF)
+ {
+ *(dest + i) = s;
+ }
+ else if (s)
+ {
+ uint32_t d = *(dest + i);
+ uint32_t ia = a ^ 0xFF;
+ UN8x4_MUL_UN8_ADD_UN8x4 (d, ia, s);
+ *(dest + i) = d;
+ }
+ }
+ else if (m)
+ {
+ uint32_t s = *(src + i);
+ if (s)
+ {
+ uint32_t d = *(dest + i);
+ UN8x4_MUL_UN8 (s, m);
+ UN8x4_MUL_UN8_ADD_UN8x4 (d, ALPHA_8 (~s), s);
+ *(dest + i) = d;
+ }
+ }
+ }
}
}
diff --git a/pixman/test/utils-prng.c b/pixman/test/utils-prng.c
index 7c2dd6a9a..967b8989a 100644
--- a/pixman/test/utils-prng.c
+++ b/pixman/test/utils-prng.c
@@ -27,6 +27,10 @@
#include "utils.h"
#include "utils-prng.h"
+#if defined(GCC_VECTOR_EXTENSIONS_SUPPORTED) && defined(__SSE2__)
+#include <xmmintrin.h>
+#endif
+
void smallprng_srand_r (smallprng_t *x, uint32_t seed)
{
uint32_t i;
@@ -77,6 +81,14 @@ store_rand_128_data (void *addr, prng_rand_128_data_t *d, int aligned)
*(uint8x16 *)addr = d->vb;
return;
}
+ else
+ {
+#ifdef __SSE2__
+ /* workaround for http://gcc.gnu.org/PR55614 */
+ _mm_storeu_si128 (addr, _mm_loadu_si128 ((__m128i *)d));
+ return;
+#endif
+ }
#endif
/* we could try something better for unaligned writes (packed attribute),
* but GCC is not very reliable: http://gcc.gnu.org/PR55454 */