aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/xorg-lib/pixman-0.19.6/0001-Generic-C-implementation-of-pixman_blt-with-overlapp.patch
blob: 795cce5bad51a2e3ecefc4b50acb34b4535f2051 (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
From 97b2bb933455f222b392b5c60a8bde82d7d6329f Mon Sep 17 00:00:00 2001
From: Siarhei Siamashka <siarhei.siamashka@nokia.com>
Date: Tue, 16 Mar 2010 16:55:28 +0100
Subject: [PATCH 1/8] Generic C implementation of pixman_blt with overlapping support

Uses memcpy/memmove functions to copy pixels, can handle the
case when both source and destination areas are in the same
image (this is useful for scrolling).

It is assumed that copying direction is only important when
using the same image for both source and destination (and
src_stride == dst_stride). Copying direction is undefined
for the images with different source and destination stride
which happen to be in the overlapped areas (but this is an
unrealistic case anyway).
---
 pixman/pixman-general.c |   21 ++++++++++++++++++---
 pixman/pixman-private.h |   43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 61 insertions(+), 3 deletions(-)

diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c
index 4d234a0..c4d2c14 100644
--- a/pixman/pixman-general.c
+++ b/pixman/pixman-general.c
@@ -280,9 +280,24 @@ general_blt (pixman_implementation_t *imp,
              int                      width,
              int                      height)
 {
-    /* We can't blit unless we have sse2 or mmx */
-
-    return FALSE;
+    uint8_t *dst_bytes = (uint8_t *)dst_bits;
+    uint8_t *src_bytes = (uint8_t *)src_bits;
+    int bpp;
+
+    if (src_bpp != dst_bpp || src_bpp & 7)
+	return FALSE;
+
+    bpp = src_bpp >> 3;
+    width *= bpp;
+    src_stride *= 4;
+    dst_stride *= 4;
+    pixman_blt_helper (src_bytes + src_y * src_stride + src_x * bpp,
+                       dst_bytes + dst_y * dst_stride + dst_x * bpp,
+                       src_stride,
+                       dst_stride,
+                       width,
+                       height);
+    return TRUE;
 }
 
 static pixman_bool_t
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index c43172b..f980454 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -10,6 +10,7 @@
 
 #include "pixman.h"
 #include <time.h>
+#include <string.h>
 #include <assert.h>
 #include <stdio.h>
 #include <string.h>
@@ -873,4 +874,46 @@ void pixman_timer_register (pixman_timer_t *timer);
 
 #endif /* PIXMAN_TIMERS */
 
+/* a helper function, can blit 8-bit images with src/dst overlapping support */
+static inline void
+pixman_blt_helper (uint8_t *src_bytes,
+                   uint8_t *dst_bytes,
+                   int      src_stride,
+                   int      dst_stride,
+                   int      width,
+                   int      height)
+{
+    /*
+     * The second part of this check is not strictly needed, but it prevents
+     * unnecessary upside-down processing of areas which belong to different
+     * images. Upside-down processing can be slower with fixed-distance-ahead
+     * prefetch and perceived as having more tearing.
+     */
+    if (src_bytes < dst_bytes + width &&
+	src_bytes + src_stride * height > dst_bytes)
+    {
+	src_bytes += src_stride * height - src_stride;
+	dst_bytes += dst_stride * height - dst_stride;
+	dst_stride = -dst_stride;
+	src_stride = -src_stride;
+	/* Horizontal scrolling to the left needs memmove */
+	if (src_bytes + width > dst_bytes)
+	{
+	    while (--height >= 0)
+	    {
+		memmove (dst_bytes, src_bytes, width);
+		dst_bytes += dst_stride;
+		src_bytes += src_stride;
+	    }
+	    return;
+	}
+    }
+    while (--height >= 0)
+    {
+	memcpy (dst_bytes, src_bytes, width);
+	dst_bytes += dst_stride;
+	src_bytes += src_stride;
+    }
+}
+
 #endif /* PIXMAN_PRIVATE_H */
-- 
1.6.6.1