summaryrefslogtreecommitdiff
path: root/src/sna/blt.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-01-06 15:26:11 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2012-01-06 17:50:01 +0000
commit9f1935bb4e894264053d94e53c99d5ad607700fb (patch)
tree689fdc95dda28ba227cf26d9ee2347a303962bb8 /src/sna/blt.c
parent141001df6c9c3485c500ed531a214c09b46c1d3b (diff)
sna: Support performing alpha-fixup on the source
By inlining the swizzling of the alpha-channel we can support BLT copies from an alpha-less pixmap to an alpha-destination. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/sna/blt.c')
-rw-r--r--src/sna/blt.c105
1 files changed, 105 insertions, 0 deletions
diff --git a/src/sna/blt.c b/src/sna/blt.c
index 7a77fa49..d28ad985 100644
--- a/src/sna/blt.c
+++ b/src/sna/blt.c
@@ -106,3 +106,108 @@ memcpy_blt(const void *src, void *dst, int bpp,
break;
}
}
+
+void
+memcpy_xor(const void *src, void *dst, int bpp,
+ int32_t src_stride, int32_t dst_stride,
+ int16_t src_x, int16_t src_y,
+ int16_t dst_x, int16_t dst_y,
+ uint16_t width, uint16_t height,
+ uint32_t and, uint32_t or)
+{
+ uint8_t *src_bytes;
+ uint8_t *dst_bytes;
+ int i;
+
+ assert(width && height);
+ assert(bpp >= 8);
+
+ DBG(("%s: src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d, bpp=%d, and=%x, xor=%x\n",
+ __FUNCTION__,
+ src_x, src_y, dst_x, dst_y,
+ width, height,
+ src_stride, dst_stride,
+ bpp, and, or));
+
+ bpp /= 8;
+ src_bytes = (uint8_t *)src + src_stride * src_y + src_x * bpp;
+ dst_bytes = (uint8_t *)dst + dst_stride * dst_y + dst_x * bpp;
+
+ if (and == 0xffffffff) {
+ switch (bpp) {
+ case 1:
+ do {
+ for (i = 0; i < width; i++)
+ dst_bytes[i] = src_bytes[i] | or;
+
+ src_bytes += src_stride;
+ dst_bytes += dst_stride;
+ } while (--height);
+ break;
+
+ case 2:
+ do {
+ uint16_t *d = (uint16_t *)dst_bytes;
+ uint16_t *s = (uint16_t *)src_bytes;
+
+ for (i = 0; i < width; i++)
+ d[i] = s[i] | or;
+
+ src_bytes += src_stride;
+ dst_bytes += dst_stride;
+ } while (--height);
+ break;
+
+ case 4:
+ do {
+ uint32_t *d = (uint32_t *)dst_bytes;
+ uint32_t *s = (uint32_t *)src_bytes;
+
+ for (i = 0; i < width; i++)
+ d[i] = s[i] | or;
+
+ src_bytes += src_stride;
+ dst_bytes += dst_stride;
+ } while (--height);
+ break;
+ }
+ } else {
+ switch (bpp) {
+ case 1:
+ do {
+ for (i = 0; i < width; i++)
+ dst_bytes[i] = (src_bytes[i] & and) | or;
+
+ src_bytes += src_stride;
+ dst_bytes += dst_stride;
+ } while (--height);
+ break;
+
+ case 2:
+ do {
+ uint16_t *d = (uint16_t *)dst_bytes;
+ uint16_t *s = (uint16_t *)src_bytes;
+
+ for (i = 0; i < width; i++)
+ d[i] = (s[i] & and) | or;
+
+ src_bytes += src_stride;
+ dst_bytes += dst_stride;
+ } while (--height);
+ break;
+
+ case 4:
+ do {
+ uint32_t *d = (uint32_t *)dst_bytes;
+ uint32_t *s = (uint32_t *)src_bytes;
+
+ for (i = 0; i < width; i++)
+ d[i] = (s[i] & and) | or;
+
+ src_bytes += src_stride;
+ dst_bytes += dst_stride;
+ } while (--height);
+ break;
+ }
+ }
+}