test_image.c revision 03b705cf
1#include <stdint.h> 2#include <stdio.h> 3#include <string.h> 4 5#include "test.h" 6 7#define MAX_DELTA 3 8 9int 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 30static void 31show_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 69static 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 117void 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 185static int 186_native_byte_order_lsb(void) 187{ 188 int x = 1; 189 return *((char *) &x) == 1; 190} 191 192void 193test_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} 219