/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* gos720 src/gos/2d/XTOP_R7/app/rendercheck/tests.c 1.1 */ /* */ /* Licensed Materials - Property of IBM */ /* */ /* Restricted Materials of IBM */ /* */ /* COPYRIGHT International Business Machines Corp. 2006 */ /* All Rights Reserved */ /* */ /* US Government Users Restricted Rights - Use, duplication or */ /* disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ /* */ /* IBM_PROLOG_END_TAG */ /* SCCSID_BEGIN_TAG */ #ifndef lint static char sccsid[] = "@(#)16 1.1 src/gos/2d/XTOP_R7/app/rendercheck/tests.c, xext, gos720 10/27/06 16:21:45"; #endif /* SCCSID_END_TAG */ /* * Copyright © 2004 Eric Anholt * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Eric Anholt not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. Eric Anholt makes no * representations about the suitability of this software for any purpose. It * is provided "as is" without express or implied warranty. * * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include "rendercheck.h" /* Note: changing the order of these colors may disrupt tests that depend on * specific colors. Just add to the end if you need. */ color4d colors[] = { {1.0, 1.0, 1.0, 1.0}, {1.0, 0, 0, 1.0}, {0, 1.0, 0, 1.0}, {0, 0, 1.0, 1.0}, {0.5, 0, 0, 0.25}, {0.5, 0, 0, .5}, {0.0, .5, 1.0, .5}, {0.0, .5, 1.0, 0} }; /* Convenience pointers to 1x1 repeating colors */ picture_info *argb32white, *argb32red, *argb32green, *argb32blue; int num_colors = sizeof(colors) / sizeof(colors[0]); struct op_info ops[] = { {PictOpClear, "Clear"}, {PictOpSrc, "Src"}, {PictOpDst, "Dst"}, {PictOpOver, "Over"}, {PictOpOverReverse, "OverReverse"}, {PictOpIn, "In"}, {PictOpInReverse, "InReverse"}, {PictOpOut, "Out"}, {PictOpOutReverse, "OutReverse"}, {PictOpAtop, "Atop"}, {PictOpAtopReverse, "AtopReverse"}, {PictOpXor, "Xor"}, {PictOpAdd, "Add"}, {PictOpSaturate, "Saturate"}, {PictOpDisjointClear, "DisjointClear"}, {PictOpDisjointSrc, "DisjointSrc"}, {PictOpDisjointDst, "DisjointDst"}, {PictOpDisjointOver, "DisjointOver"}, {PictOpDisjointOverReverse, "DisjointOverReverse"}, {PictOpDisjointIn, "DisjointIn"}, {PictOpDisjointInReverse, "DisjointInReverse"}, {PictOpDisjointOut, "DisjointOut"}, {PictOpDisjointOutReverse, "DisjointOutReverse"}, {PictOpDisjointAtop, "DisjointAtop"}, {PictOpDisjointAtopReverse, "DisjointAtopReverse"}, {PictOpDisjointXor, "DisjointXor"}, {PictOpConjointClear, "ConjointClear"}, {PictOpConjointSrc, "ConjointSrc"}, {PictOpConjointDst, "ConjointDst"}, {PictOpConjointOver, "ConjointOver"}, {PictOpConjointOverReverse, "ConjointOverReverse"}, {PictOpConjointIn, "ConjointIn"}, {PictOpConjointInReverse, "ConjointInReverse"}, {PictOpConjointOut, "ConjointOut"}, {PictOpConjointOutReverse, "ConjointOutReverse"}, {PictOpConjointAtop, "ConjointAtop"}, {PictOpConjointAtopReverse, "ConjointAtopReverse"}, {PictOpConjointXor, "ConjointXor"}, }; int num_ops = sizeof(ops) / sizeof(ops[0]); #define round_pix(pix, mask) \ ((double)((int)(pix * (mask ) + .5)) / (double)(mask)) void color_correct(picture_info *pi, color4d *color) { if (!pi->format->direct.redMask) { color->r = 0.0; color->g = 0.0; color->b = 0.0; } else { color->r = round_pix(color->r, pi->format->direct.redMask); color->g = round_pix(color->g, pi->format->direct.greenMask); color->b = round_pix(color->b, pi->format->direct.blueMask); } if (!pi->format->direct.alphaMask) color->a = 1.0; else color->a = round_pix(color->a, pi->format->direct.alphaMask); } void get_pixel(Display *dpy, picture_info *pi, int x, int y, color4d *color) { XImage *image; unsigned long val; unsigned long rm, gm, bm, am; image = XGetImage(dpy, pi->d, x, y, 1, 1, 0xffffffff, ZPixmap); val = *(unsigned long *)image->data; rm = pi->format->direct.redMask << pi->format->direct.red; gm = pi->format->direct.greenMask << pi->format->direct.green; bm = pi->format->direct.blueMask << pi->format->direct.blue; am = pi->format->direct.alphaMask << pi->format->direct.alpha; if (am != 0) color->a = (double)(val & am) / (double)am; else color->a = 1.0; if (rm != 0) { color->r = (double)(val & rm) / (double)rm; color->g = (double)(val & gm) / (double)gm; color->b = (double)(val & bm) / (double)bm; } else { color->r = 0.0; color->g = 0.0; color->b = 0.0; } XDestroyImage(image); } int eval_diff(char *name, color4d *expected, color4d *test, int x, int y, Bool verbose) { double rscale, gscale, bscale, ascale; double rdiff, gdiff, bdiff, adiff, diff; /* XXX: Need to be provided mask shifts so we can produce useful error * values. */ rscale = 1.0 * (1 << 5); gscale = 1.0 * (1 << 6); bscale = 1.0 * (1 << 5); ascale = 1.0; rdiff = fabs(test->r - expected->r) * rscale; bdiff = fabs(test->g - expected->g) * gscale; gdiff = fabs(test->b - expected->b) * bscale; adiff = fabs(test->a - expected->a) * ascale; /*rdiff = log2(1.0 + rdiff); gdiff = log2(1.0 + gdiff); bdiff = log2(1.0 + bdiff); adiff = log2(1.0 + adiff);*/ diff = max(max(max(rdiff, gdiff), bdiff), adiff); if (diff > 3.0) { printf("%s test error of %.4f at (%d, %d) --\n" "got: %.2f %.2f %.2f %.2f\n" "expected: %.2f %.2f %.2f %.2f\n", name, diff, x, y, test->r, test->g, test->b, test->a, expected->r, expected->g, expected->b, expected->a); return FALSE; } else if (verbose) { printf("%s test succeeded at (%d, %d) with %.4f: " "%.2f %.2f %.2f %.2f\n", name, x, y, diff, expected->r, expected->g, expected->b, expected->a); } return TRUE; } void argb_fill(Display *dpy, picture_info *p, int x, int y, int w, int h, float a, float r, float g, float b) { XRenderColor rendercolor; rendercolor.red = r * 65535; rendercolor.green = g * 65535; rendercolor.blue = b * 65535; rendercolor.alpha = a * 65535; XRenderFillRectangle(dpy, PictOpSrc, p->pict, &rendercolor, x, y, w, h); } Bool do_tests(Display *dpy, picture_info *win) { int i, j, src, dst = 0, mask; int num_dests, num_formats; picture_info *dests, *pictures_1x1, *pictures_10x10, picture_3x3, *pictures_solid; int success_mask = 0, tests_passed = 0, tests_total = 0; num_dests = 3; dests = (picture_info *)malloc(num_dests * sizeof(dests[0])); if (dests == NULL) errx(1, "malloc error"); dests[0].format = XRenderFindStandardFormat(dpy, PictStandardARGB32); dests[1].format = XRenderFindStandardFormat(dpy, PictStandardRGB24); dests[2].format = XRenderFindStandardFormat(dpy, PictStandardA8); /* dests[3].format = XRenderFindStandardFormat(dpy, PictStandardA4); dests[4].format = XRenderFindStandardFormat(dpy, PictStandardA1); */ for (i = 0; i < num_dests; i++) { dests[i].d = XCreatePixmap(dpy, RootWindow(dpy, 0), win_width, win_height, dests[i].format->depth); dests[i].pict = XRenderCreatePicture(dpy, dests[i].d, dests[i].format, 0, NULL); dests[i].name = (char *)malloc(20); if (dests[i].name == NULL) errx(1, "malloc error"); describe_format(dests[i].name, 20, dests[i].format); } num_formats = 3; pictures_1x1 = (picture_info *)malloc(num_colors * num_formats * sizeof(picture_info)); if (pictures_1x1 == NULL) errx(1, "malloc error"); for (i = 0; i < num_colors * num_formats; i++) { XRenderPictureAttributes pa; color4d *c = &colors[i / num_formats]; /* The standard PictFormat numbers go from 0 to 4 */ pictures_1x1[i].format = XRenderFindStandardFormat(dpy, i % num_formats); pictures_1x1[i].d = XCreatePixmap(dpy, RootWindow(dpy, 0), 1, 1, pictures_1x1[i].format->depth); pa.repeat = TRUE; pictures_1x1[i].pict = XRenderCreatePicture(dpy, pictures_1x1[i].d, pictures_1x1[i].format, CPRepeat, &pa); pictures_1x1[i].name = (char *)malloc(20); if (pictures_1x1[i].name == NULL) errx(1, "malloc error"); sprintf(pictures_1x1[i].name, "1x1R "); describe_format(pictures_1x1[i].name + strlen(pictures_1x1[i].name), 20 - strlen(pictures_1x1[i].name), pictures_1x1[i].format); argb_fill(dpy, &pictures_1x1[i], 0, 0, 1, 1, c->a, c->r, c->g, c->b); pictures_1x1[i].color = *c; color_correct(&pictures_1x1[i], &pictures_1x1[i].color); } argb32white = &pictures_1x1[0 * num_formats]; argb32red = &pictures_1x1[1 * num_formats]; argb32green = &pictures_1x1[2 * num_formats]; argb32blue = &pictures_1x1[3 * num_formats]; pictures_10x10 = (picture_info *)malloc(num_colors * num_formats * sizeof(picture_info)); if (pictures_10x10 == NULL) errx(1, "malloc error"); for (i = 0; i < num_colors * num_formats; i++) { XRenderPictureAttributes pa; color4d *c = &colors[i / num_formats]; /* The standard PictFormat numbers go from 0 to 4 */ pictures_10x10[i].format = XRenderFindStandardFormat(dpy, i % num_formats); pictures_10x10[i].d = XCreatePixmap(dpy, RootWindow(dpy, 0), 10, 10, pictures_10x10[i].format->depth); pa.repeat = TRUE; pictures_10x10[i].pict = XRenderCreatePicture(dpy, pictures_10x10[i].d, pictures_10x10[i].format, 0, NULL); pictures_10x10[i].name = (char *)malloc(20); if (pictures_10x10[i].name == NULL) errx(1, "malloc error"); sprintf(pictures_10x10[i].name, "10x10 "); describe_format(pictures_10x10[i].name + strlen(pictures_10x10[i].name), 20 - strlen(pictures_10x10[i].name), pictures_10x10[i].format); argb_fill(dpy, &pictures_10x10[i], 0, 0, 10, 10, c->a, c->r, c->g, c->b); pictures_10x10[i].color = *c; color_correct(&pictures_10x10[i], &pictures_10x10[i].color); } picture_3x3.d = XCreatePixmap(dpy, RootWindow(dpy, 0), 3, 3, 32); picture_3x3.format = XRenderFindStandardFormat(dpy, PictStandardARGB32); picture_3x3.pict = XRenderCreatePicture(dpy, picture_3x3.d, picture_3x3.format, 0, NULL); picture_3x3.name = "3x3 sample picture"; for (i = 0; i < 9; i++) { int x = i % 3; int y = i / 3; color4d *c = &colors[i % num_colors]; argb_fill(dpy, &picture_3x3, x, y, 1, 1, c->a, c->r, c->g, c->b); } pictures_solid = malloc(num_colors * sizeof(picture_info)); for (i = 0; i < num_colors; i++) { pictures_solid[i].color = colors[i]; XRenderColor c; c.alpha = (int)(colors[i].a*65535); c.red = (int)(colors[i].r*65535); c.green = (int)(colors[i].g*65535); c.blue = (int)(colors[i].b*65535); pictures_solid[i].pict = XRenderCreateSolidFill(dpy, &c); pictures_solid[i].name = "Solid"; } #define RECORD_RESULTS() \ do { \ group_ok = group_ok && ok; \ if (ok) \ tests_passed++; \ tests_total++; \ } while (0) if (enabled_tests & TEST_FILL) { Bool ok, group_ok = TRUE; printf("Beginning testing of filling of 1x1R pictures\n"); for (i = 0; i < num_colors * num_formats; i++) { ok = fill_test(dpy, win, &pictures_1x1[i]); RECORD_RESULTS(); } printf("Beginning testing of filling of 10x10 pictures\n"); for (i = 0; i < num_colors * num_formats; i++) { ok = fill_test(dpy, win, &pictures_10x10[i]); RECORD_RESULTS(); } if (group_ok) success_mask |= TEST_FILL; } if (enabled_tests & TEST_DSTCOORDS) { Bool ok, group_ok = TRUE; printf("Beginning dest coords test\n"); /* 0 and num_formats should result in ARGB8888 red on ARGB8888 white. */ ok = dstcoords_test(dpy, win, &dests[0], &pictures_1x1[0], &pictures_1x1[num_formats]); RECORD_RESULTS(); if (group_ok) success_mask |= TEST_DSTCOORDS; } if (enabled_tests & TEST_SRCCOORDS) { Bool ok, group_ok = TRUE; printf("Beginning src coords test\n"); ok = srccoords_test(dpy, win, &pictures_1x1[0], FALSE); RECORD_RESULTS(); if (group_ok) success_mask |= TEST_SRCCOORDS; } if (enabled_tests & TEST_MASKCOORDS) { Bool ok, group_ok = TRUE; printf("Beginning mask coords test\n"); ok = srccoords_test(dpy, win, &pictures_1x1[0], TRUE); RECORD_RESULTS(); if (group_ok) success_mask |= TEST_MASKCOORDS; } if (enabled_tests & TEST_TSRCCOORDS) { Bool ok, group_ok = TRUE; printf("Beginning transformed src coords test\n"); ok = trans_coords_test(dpy, win, &pictures_1x1[0], FALSE); RECORD_RESULTS(); if (group_ok) success_mask |= TEST_TSRCCOORDS; } if (enabled_tests & TEST_TMASKCOORDS) { Bool ok, group_ok = TRUE; printf("Beginning transformed mask coords test\n"); ok = trans_coords_test(dpy, win, &pictures_1x1[0], TRUE); RECORD_RESULTS(); if (group_ok) success_mask |= TEST_TMASKCOORDS; } if (enabled_tests & TEST_BLEND) { Bool ok, group_ok = TRUE; for (i = 0; i < num_ops; i++) { for (j = 0; j <= num_dests; j++) { picture_info *pi; if (j != num_dests) pi = &dests[j]; else pi = win; printf("Beginning %s blend test on %s\n", ops[i].name, pi->name); for (src = 0; src < num_colors * num_formats; src++) { for (dst = 0; dst < num_colors; dst++) { ok = blend_test(dpy, win, pi, i, &pictures_1x1[src], &pictures_1x1[dst]); RECORD_RESULTS(); ok = blend_test(dpy, win, pi, i, &pictures_10x10[src], &pictures_1x1[dst]); RECORD_RESULTS(); } } for (src = 0; src < num_colors; src++) { for (dst = 0; dst < num_colors; dst++) { ok = blend_test(dpy, win, pi, i, &pictures_solid[src], &pictures_1x1[dst]); RECORD_RESULTS(); } } } } if (group_ok) success_mask |= TEST_BLEND; } if (enabled_tests & TEST_COMPOSITE) { Bool ok, group_ok = TRUE; for (i = 0; i < num_ops; i++) { for (j = 0; j <= num_dests; j++) { picture_info *pi; if (j != num_dests) pi = &dests[j]; else pi = win; printf("Beginning %s composite mask test on %s\n", ops[i].name, pi->name); for (src = 0; src < num_colors; src++) { for (mask = 0; mask < num_colors; mask++) { for (dst = 0; dst < num_colors; dst++) { ok = composite_test(dpy, win, pi, i, &pictures_10x10[src], &pictures_10x10[mask], &pictures_1x1[dst], FALSE, TRUE); RECORD_RESULTS(); ok = composite_test(dpy, win, pi, i, &pictures_1x1[src], &pictures_10x10[mask], &pictures_1x1[dst], FALSE, TRUE); RECORD_RESULTS(); ok = composite_test(dpy, win, pi, i, &pictures_10x10[src], &pictures_1x1[mask], &pictures_1x1[dst], FALSE, TRUE); RECORD_RESULTS(); ok = composite_test(dpy, win, pi, i, &pictures_1x1[src], &pictures_1x1[mask], &pictures_1x1[dst], FALSE, TRUE); RECORD_RESULTS(); } } } } } if (group_ok) success_mask |= TEST_COMPOSITE; } if (enabled_tests & TEST_CACOMPOSITE) { Bool ok, group_ok = TRUE; for (i = 0; i < num_ops; i++) { for (j = 0; j <= num_dests; j++) { picture_info *pi; if (j != num_dests) pi = &dests[j]; else pi = win; printf("Beginning %s composite CA mask test on %s\n", ops[i].name, pi->name); for (src = 0; src < num_colors; src++) { for (mask = 0; mask < num_colors; mask++) { for (dst = 0; dst < num_colors; dst++) { ok = composite_test(dpy, win, pi, i, &pictures_10x10[src], &pictures_10x10[mask], &pictures_1x1[dst], TRUE, TRUE); RECORD_RESULTS(); ok = composite_test(dpy, win, pi, i, &pictures_1x1[src], &pictures_10x10[mask], &pictures_1x1[dst], TRUE, TRUE); RECORD_RESULTS(); ok = composite_test(dpy, win, pi, i, &pictures_10x10[src], &pictures_1x1[mask], &pictures_1x1[dst], TRUE, TRUE); RECORD_RESULTS(); ok = composite_test(dpy, win, pi, i, &pictures_1x1[src], &pictures_1x1[mask], &pictures_1x1[dst], TRUE, TRUE); RECORD_RESULTS(); } } } } } if (group_ok) success_mask |= TEST_CACOMPOSITE; } if (enabled_tests & TEST_GRADIENTS) { Bool ok, group_ok = TRUE; for (i = 0; i < num_ops; i++) { for (j = 0; j <= num_dests; j++) { picture_info *pi; if (j != num_dests) pi = &dests[j]; else pi = win; printf("Beginning %s linear gradient test on %s\n", ops[i].name, pi->name); for (src = 0; src < num_colors; src++) { for (mask = 0; mask < num_colors; mask++) { ok = linear_gradient_test(dpy, win, pi, i, &pictures_1x1[dst]); RECORD_RESULTS(); } } } } if (group_ok) success_mask |= TEST_GRADIENTS; } if (enabled_tests & TEST_REPEAT) { Bool ok, group_ok = TRUE; for (i = 0; i < num_ops; i++) { for (j = 0; j <= num_dests; j++) { picture_info *pi; if (j != num_dests) pi = &dests[j]; else pi = win; printf("Beginning %s src repeat test on %s\n", ops[i].name, pi->name); /* Test with white dest, and generated repeating src * consisting of colors 1 and 2 (r, g). */ ok = repeat_test(dpy, win, pi, i, argb32white, argb32red, argb32green, FALSE); RECORD_RESULTS(); printf("Beginning %s mask repeat test on %s\n", ops[i].name, pi->name); /* Test with white dest, translucent red src, and generated * repeating mask consisting of colors 1 and 2 (r, g). */ ok = repeat_test(dpy, win, pi, i, argb32white, argb32red, argb32green, TRUE); RECORD_RESULTS(); } } if (group_ok) success_mask |= TEST_REPEAT; } if (enabled_tests & TEST_TRIANGLES) { Bool ok, group_ok = TRUE; for (i = 0; i < num_ops; i++) { for (j = 0; j <= num_dests; j++) { picture_info *pi; if (j != num_dests) pi = &dests[j]; else pi = win; printf("Beginning %s Triangles test on %s\n", ops[i].name, pi->name); ok = triangles_test(dpy, win, pi, i, &pictures_1x1[num_formats], &pictures_1x1[0]); RECORD_RESULTS(); printf("Beginning %s TriStrip test on %s\n", ops[i].name, pi->name); ok = tristrip_test(dpy, win, pi, i, &pictures_1x1[num_formats], &pictures_1x1[0]); RECORD_RESULTS(); printf("Beginning %s TriFan test on %s\n", ops[i].name, pi->name); ok = trifan_test(dpy, win, pi, i, &pictures_1x1[num_formats], &pictures_1x1[0]); RECORD_RESULTS(); } } if (group_ok) success_mask |= TEST_TRIANGLES; } printf("%d tests passed of %d total\n", tests_passed, tests_total); return tests_passed == tests_total; }