take two
[profile/ivi/xorg-x11-drv-intel.git] / test / test_image.c
1 #include <stdint.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 #include "test.h"
6
7 #define MAX_DELTA 3
8
9 int pixel_difference(uint32_t a, uint32_t b)
10 {
11         int max = 0;
12         int i;
13
14         for (i = 0; i < 32; i += 8) {
15                 uint8_t ac = (a >> i) & 0xff;
16                 uint8_t bc = (b >> i) & 0xff;
17                 int d;
18
19                 if (ac > bc)
20                         d = ac - bc;
21                 else
22                         d = bc - ac;
23                 if (d > max)
24                         max = d;
25         }
26
27         return max;
28 }
29
30 static void
31 show_pixels(char *buf,
32             const XImage *real, const XImage *ref,
33             int x, int y, int w, int h)
34 {
35         int i, j, len = 0;
36
37         for (j = y - 2; j <= y + 2; j++) {
38                 if (j < 0 || j >= h)
39                         continue;
40
41                 for (i = x - 2; i <= x + 2; i++) {
42                         if (i < 0 || i >= w)
43                                 continue;
44
45                         len += sprintf(buf+len,
46                                        "%08x ",
47                                        *(uint32_t*)(real->data +
48                                                     j*real->bytes_per_line +
49                                                     i*real->bits_per_pixel/8));
50                 }
51
52                 len += sprintf(buf+len, "\t");
53
54                 for (i = x - 2; i <= x + 2; i++) {
55                         if (i < 0 || i >= w)
56                                 continue;
57
58                         len += sprintf(buf+len,
59                                        "%08x ",
60                                        *(uint32_t*)(ref->data +
61                                                     j*real->bytes_per_line +
62                                                     i*real->bits_per_pixel/8));
63                 }
64
65                 len += sprintf(buf+len, "\n");
66         }
67 }
68
69 static void test_compare_fallback(struct test *t,
70                                   Drawable real_draw, XRenderPictFormat *real_format,
71                                   Drawable ref_draw, XRenderPictFormat *ref_format,
72                                   int x, int y, int w, int h)
73 {
74         XImage *real_image, *ref_image;
75         char *real, *ref;
76         char buf[600];
77         uint32_t mask;
78         int i, j;
79
80         die_unless(real_format->depth == ref_format->depth);
81
82         real_image = XGetImage(t->real.dpy, real_draw,
83                                x, y, w, h,
84                                AllPlanes, ZPixmap);
85         real = real_image->data;
86
87         ref_image = XGetImage(t->ref.dpy, ref_draw,
88                               x, y, w, h,
89                               AllPlanes, ZPixmap);
90         ref = ref_image->data;
91
92         mask = depth_mask(real_image->depth);
93
94         /* Start with an exact comparison. However, one quicky desires
95          * a fuzzy comparator to hide hardware inaccuracies...
96          */
97         for (j = 0; j < h; j++) {
98                 for (i = 0; i < w; i++) {
99                         uint32_t a = ((uint32_t *)real)[i] & mask;
100                         uint32_t b = ((uint32_t *)ref)[i] & mask;
101                         if (a != b && pixel_difference(a, b) > MAX_DELTA) {
102                                 show_pixels(buf,
103                                             real_image, ref_image,
104                                             i, j, w, h);
105                                 die("discrepancy found at (%d+%d, %d+%d): found %08x, expected %08x (delta: %d)\n%s",
106                                     x,i, y,j, a, b, pixel_difference(a, b), buf);
107                         }
108                 }
109                 real += real_image->bytes_per_line;
110                 ref += ref_image->bytes_per_line;
111         }
112
113         XDestroyImage(real_image);
114         XDestroyImage(ref_image);
115 }
116
117 void test_compare(struct test *t,
118                   Drawable real_draw, XRenderPictFormat *real_format,
119                   Drawable ref_draw, XRenderPictFormat *ref_format,
120                   int x, int y, int w, int h,
121                   const char *info)
122 {
123         XImage real_image, ref_image;
124         Pixmap tmp;
125         char *real, *ref;
126         char buf[600];
127         uint32_t mask;
128         int i, j;
129         XGCValues gcv;
130         GC gc;
131
132         if (w * h * 4 > t->real.max_shm_size)
133                 return test_compare_fallback(t,
134                                              real_draw, real_format,
135                                              ref_draw, ref_format,
136                                              x, y, w, h);
137
138         test_init_image(&real_image, &t->real.shm, real_format, w, h);
139         test_init_image(&ref_image, &t->ref.shm, ref_format, w, h);
140
141         gcv.graphics_exposures = 0;
142
143         die_unless(real_image.depth == ref_image.depth);
144         die_unless(real_image.bits_per_pixel == ref_image.bits_per_pixel);
145         die_unless(real_image.bits_per_pixel == 32);
146
147         mask = depth_mask(real_image.depth);
148
149         tmp = XCreatePixmap(t->real.dpy, real_draw, w, h, real_image.depth);
150         gc = XCreateGC(t->real.dpy, tmp, GCGraphicsExposures, &gcv);
151         XCopyArea(t->real.dpy, real_draw, tmp, gc, x, y, w, h, 0, 0);
152         XShmGetImage(t->real.dpy, tmp, &real_image, 0, 0, AllPlanes);
153         XFreeGC(t->real.dpy, gc);
154         XFreePixmap(t->real.dpy, tmp);
155         real = real_image.data;
156
157         tmp = XCreatePixmap(t->ref.dpy, ref_draw, w, h, ref_image.depth);
158         gc = XCreateGC(t->ref.dpy, tmp, GCGraphicsExposures, &gcv);
159         XCopyArea(t->ref.dpy, ref_draw, tmp, gc, x, y, w, h, 0, 0);
160         XShmGetImage(t->ref.dpy, tmp, &ref_image, 0, 0, AllPlanes);
161         XFreeGC(t->ref.dpy, gc);
162         XFreePixmap(t->ref.dpy, tmp);
163         ref = ref_image.data;
164
165         /* Start with an exact comparison. However, one quicky desires
166          * a fuzzy comparator to hide hardware inaccuracies...
167          */
168         for (j = 0; j < h; j++) {
169                 for (i = 0; i < w; i++) {
170                         uint32_t a = ((uint32_t *)real)[i] & mask;
171                         uint32_t b = ((uint32_t *)ref)[i] & mask;
172                         if (a != b && pixel_difference(a, b) > MAX_DELTA) {
173                                 show_pixels(buf,
174                                             &real_image, &ref_image,
175                                             i, j, w, h);
176                                 die("discrepancy found at (%d+%d, %d+%d): found %08x, expected %08x (delta: %d)\n%s%s\n",
177                                     x,i, y,j, a, b, pixel_difference(a, b), buf, info);
178                         }
179                 }
180                 real += real_image.bytes_per_line;
181                 ref += ref_image.bytes_per_line;
182         }
183 }
184
185 static int
186 _native_byte_order_lsb(void)
187 {
188         int x = 1;
189         return *((char *) &x) == 1;
190 }
191
192 void
193 test_init_image(XImage *ximage,
194                 XShmSegmentInfo *shm,
195                 XRenderPictFormat *format,
196                 int width, int height)
197 {
198         int native_byte_order = _native_byte_order_lsb() ? LSBFirst : MSBFirst;
199
200         ximage->width = width;
201         ximage->height = height;
202         ximage->format = ZPixmap;
203         ximage->data = shm->shmaddr;
204         ximage->obdata = (void *)shm;
205         ximage->byte_order = native_byte_order;
206         ximage->bitmap_unit = 32;
207         ximage->bitmap_bit_order = native_byte_order;
208         ximage->bitmap_pad = 32;
209         ximage->depth = format->depth;
210         ximage->bytes_per_line = 4*width;
211         ximage->bits_per_pixel = 32;
212         ximage->red_mask = 0xff << 16;
213         ximage->green_mask = 0xff << 8;
214         ximage->blue_mask = 0xff << 0;
215         ximage->xoffset = 0;
216
217         XInitImage(ximage);
218 }