summaryrefslogtreecommitdiff
path: root/x11/pixman/patches/patch-bc
blob: 4a94a9625b7c934d808b81274a6ef4d07e6d13e0 (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
$NetBSD: patch-bc,v 1.1 2011/10/27 16:52:51 drochner Exp $

--- pixman/pixman.c.orig	2011-07-04 20:22:40.000000000 +0000
+++ pixman/pixman.c
@@ -162,6 +162,57 @@ optimize_operator (pixman_op_t     op,
     return operator_table[op].opaque_info[is_dest_opaque | is_source_opaque];
 }
 
+static void
+apply_workaround (pixman_image_t *image,
+		  int32_t *       x,
+		  int32_t *       y,
+		  uint32_t **     save_bits,
+		  int *           save_dx,
+		  int *           save_dy)
+{
+    if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND))
+    {
+	/* Some X servers generate images that point to the
+	 * wrong place in memory, but then set the clip region
+	 * to point to the right place. Because of an old bug
+	 * in pixman, this would actually work.
+	 *
+	 * Here we try and undo the damage
+	 */
+	int bpp = PIXMAN_FORMAT_BPP (image->bits.format) / 8;
+	pixman_box32_t *extents;
+	uint8_t *t;
+	int dx, dy;
+	
+	extents = pixman_region32_extents (&(image->common.clip_region));
+	dx = extents->x1;
+	dy = extents->y1;
+	
+	*save_bits = image->bits.bits;
+	
+	*x -= dx;
+	*y -= dy;
+	pixman_region32_translate (&(image->common.clip_region), -dx, -dy);
+	
+	t = (uint8_t *)image->bits.bits;
+	t += dy * image->bits.rowstride * 4 + dx * bpp;
+	image->bits.bits = (uint32_t *)t;
+	
+	*save_dx = dx;
+	*save_dy = dy;
+    }
+}
+
+static void
+unapply_workaround (pixman_image_t *image, uint32_t *bits, int dx, int dy)
+{
+    if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND))
+    {
+	image->bits.bits = bits;
+	pixman_region32_translate (&image->common.clip_region, dx, dy);
+    }
+}
+
 /*
  * Computing composite region
  */
@@ -690,6 +741,13 @@ pixman_image_composite32 (pixman_op_t   
     uint32_t src_flags, mask_flags, dest_flags;
     pixman_region32_t region;
     pixman_box32_t *extents;
+    uint32_t *src_bits;
+    int src_dx, src_dy;
+    uint32_t *mask_bits;
+    int mask_dx, mask_dy;
+    uint32_t *dest_bits;
+    int dest_dx, dest_dy;
+    pixman_bool_t need_workaround;
     pixman_implementation_t *imp;
     pixman_composite_func_t func;
 
@@ -727,6 +785,16 @@ pixman_image_composite32 (pixman_op_t   
 	    src_format = mask_format = PIXMAN_rpixbuf;
     }
 
+    /* Check for workaround */
+    need_workaround = (src_flags | mask_flags | dest_flags) & FAST_PATH_NEEDS_WORKAROUND;
+
+    if (need_workaround)
+    {
+	apply_workaround (src, &src_x, &src_y, &src_bits, &src_dx, &src_dy);
+	apply_workaround (mask, &mask_x, &mask_y, &mask_bits, &mask_dx, &mask_dy);
+	apply_workaround (dest, &dest_x, &dest_y, &dest_bits, &dest_dx, &dest_dy);
+    }
+
     pixman_region32_init (&region);
 
     if (!pixman_compute_composite_region32 (
@@ -793,6 +861,13 @@ pixman_image_composite32 (pixman_op_t   
     }
 
 out:
+    if (need_workaround)
+    {
+	unapply_workaround (src, src_bits, src_dx, src_dy);
+	unapply_workaround (mask, mask_bits, mask_dx, mask_dy);
+	unapply_workaround (dest, dest_bits, dest_dx, dest_dy);
+    }
+
     pixman_region32_fini (&region);
 }