summaryrefslogtreecommitdiff
path: root/test/test_image.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/test_image.c')
-rw-r--r--test/test_image.c217
1 files changed, 217 insertions, 0 deletions
diff --git a/test/test_image.c b/test/test_image.c
new file mode 100644
index 00000000..a2fdbf0b
--- /dev/null
+++ b/test/test_image.c
@@ -0,0 +1,217 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "test.h"
+
+#define MAX_DELTA 3
+
+int pixel_difference(uint32_t a, uint32_t b)
+{
+ int max = 0;
+ int i;
+
+ for (i = 0; i < 32; i += 8) {
+ uint8_t ac = (a >> i) & 0xff;
+ uint8_t bc = (b >> i) & 0xff;
+ int d;
+
+ if (ac > bc)
+ d = ac - bc;
+ else
+ d = bc - ac;
+ if (d > max)
+ max = d;
+ }
+
+ return max;
+}
+
+static void
+show_pixels(char *buf,
+ const XImage *real, const XImage *ref,
+ int x, int y, int w, int h)
+{
+ int i, j, len = 0;
+
+ for (j = y - 2; j <= y + 2; j++) {
+ if (j < 0 || j >= h)
+ continue;
+
+ for (i = x - 2; i <= x + 2; i++) {
+ if (i < 0 || i >= w)
+ continue;
+
+ len += sprintf(buf+len,
+ "%08x ",
+ *(uint32_t*)(real->data +
+ j*real->bytes_per_line +
+ i*real->bits_per_pixel/8));
+ }
+
+ len += sprintf(buf+len, "\t");
+
+ for (i = x - 2; i <= x + 2; i++) {
+ if (i < 0 || i >= w)
+ continue;
+
+ len += sprintf(buf+len,
+ "%08x ",
+ *(uint32_t*)(ref->data +
+ j*real->bytes_per_line +
+ i*real->bits_per_pixel/8));
+ }
+
+ len += sprintf(buf+len, "\n");
+ }
+}
+
+static void test_compare_fallback(struct test *t,
+ Drawable real_draw, XRenderPictFormat *real_format,
+ Drawable ref_draw, XRenderPictFormat *ref_format,
+ int x, int y, int w, int h)
+{
+ XImage *real_image, *ref_image;
+ char *real, *ref;
+ char buf[600];
+ uint32_t mask;
+ int i, j;
+
+ die_unless(real_format->depth == ref_format->depth);
+
+ real_image = XGetImage(t->real.dpy, real_draw,
+ x, y, w, h,
+ AllPlanes, ZPixmap);
+ real = real_image->data;
+
+ ref_image = XGetImage(t->ref.dpy, ref_draw,
+ x, y, w, h,
+ AllPlanes, ZPixmap);
+ ref = ref_image->data;
+
+ mask = depth_mask(real_image->depth);
+
+ /* Start with an exact comparison. However, one quicky desires
+ * a fuzzy comparator to hide hardware inaccuracies...
+ */
+ for (j = 0; j < h; j++) {
+ for (i = 0; i < w; i++) {
+ uint32_t a = ((uint32_t *)real)[i] & mask;
+ uint32_t b = ((uint32_t *)ref)[i] & mask;
+ if (a != b && pixel_difference(a, b) > MAX_DELTA) {
+ show_pixels(buf,
+ real_image, ref_image,
+ i, j, w, h);
+ die("discrepancy found at (%d+%d, %d+%d): found %08x, expected %08x (delta: %d)\n%s",
+ x,i, y,j, a, b, pixel_difference(a, b), buf);
+ }
+ }
+ real += real_image->bytes_per_line;
+ ref += ref_image->bytes_per_line;
+ }
+
+ XDestroyImage(real_image);
+ XDestroyImage(ref_image);
+}
+
+void test_compare(struct test *t,
+ Drawable real_draw, XRenderPictFormat *real_format,
+ Drawable ref_draw, XRenderPictFormat *ref_format,
+ int x, int y, int w, int h)
+{
+ XImage real_image, ref_image;
+ Pixmap tmp;
+ char *real, *ref;
+ char buf[600];
+ uint32_t mask;
+ int i, j;
+ XGCValues gcv;
+ GC gc;
+
+ if (w * h * 4 > t->real.max_shm_size)
+ return test_compare_fallback(t,
+ real_draw, real_format,
+ ref_draw, ref_format,
+ x, y, w, h);
+
+ test_init_image(&real_image, &t->real.shm, real_format, w, h);
+ test_init_image(&ref_image, &t->ref.shm, ref_format, w, h);
+
+ gcv.graphics_exposures = 0;
+
+ die_unless(real_image.depth == ref_image.depth);
+ die_unless(real_image.bits_per_pixel == ref_image.bits_per_pixel);
+ die_unless(real_image.bits_per_pixel == 32);
+
+ mask = depth_mask(real_image.depth);
+
+ tmp = XCreatePixmap(t->real.dpy, real_draw, w, h, real_image.depth);
+ gc = XCreateGC(t->real.dpy, tmp, GCGraphicsExposures, &gcv);
+ XCopyArea(t->real.dpy, real_draw, tmp, gc, x, y, w, h, 0, 0);
+ XShmGetImage(t->real.dpy, tmp, &real_image, 0, 0, AllPlanes);
+ XFreeGC(t->real.dpy, gc);
+ XFreePixmap(t->real.dpy, tmp);
+ real = real_image.data;
+
+ tmp = XCreatePixmap(t->ref.dpy, ref_draw, w, h, ref_image.depth);
+ gc = XCreateGC(t->ref.dpy, tmp, GCGraphicsExposures, &gcv);
+ XCopyArea(t->ref.dpy, ref_draw, tmp, gc, x, y, w, h, 0, 0);
+ XShmGetImage(t->ref.dpy, tmp, &ref_image, 0, 0, AllPlanes);
+ XFreeGC(t->ref.dpy, gc);
+ XFreePixmap(t->ref.dpy, tmp);
+ ref = ref_image.data;
+
+ /* Start with an exact comparison. However, one quicky desires
+ * a fuzzy comparator to hide hardware inaccuracies...
+ */
+ for (j = 0; j < h; j++) {
+ for (i = 0; i < w; i++) {
+ uint32_t a = ((uint32_t *)real)[i] & mask;
+ uint32_t b = ((uint32_t *)ref)[i] & mask;
+ if (a != b && pixel_difference(a, b) > MAX_DELTA) {
+ show_pixels(buf,
+ &real_image, &ref_image,
+ i, j, w, h);
+ die("discrepancy found at (%d+%d, %d+%d): found %08x, expected %08x (delta: %d)\n%s",
+ x,i, y,j, a, b, pixel_difference(a, b), buf);
+ }
+ }
+ real += real_image.bytes_per_line;
+ ref += ref_image.bytes_per_line;
+ }
+}
+
+static int
+_native_byte_order_lsb(void)
+{
+ int x = 1;
+ return *((char *) &x) == 1;
+}
+
+void
+test_init_image(XImage *ximage,
+ XShmSegmentInfo *shm,
+ XRenderPictFormat *format,
+ int width, int height)
+{
+ int native_byte_order = _native_byte_order_lsb() ? LSBFirst : MSBFirst;
+
+ ximage->width = width;
+ ximage->height = height;
+ ximage->format = ZPixmap;
+ ximage->data = shm->shmaddr;
+ ximage->obdata = (void *)shm;
+ ximage->byte_order = native_byte_order;
+ ximage->bitmap_unit = 32;
+ ximage->bitmap_bit_order = native_byte_order;
+ ximage->bitmap_pad = 32;
+ ximage->depth = format->depth;
+ ximage->bytes_per_line = 4*width;
+ ximage->bits_per_pixel = 32;
+ ximage->red_mask = 0xff << 16;
+ ximage->green_mask = 0xff << 8;
+ ximage->blue_mask = 0xff << 0;
+ ximage->xoffset = 0;
+
+ XInitImage(ximage);
+}