Buggy repeat modes in Render
Carl Worth
cworth at cworth.org
Tue Feb 26 16:33:32 PST 2008
I've been getting reports[1] that recent snapshots of cairo have been
getting the X server to render garbage or to crash when asking Render
to draw repeating patterns.
I've had a hard time chasing down which versions of X have bugs with
the various repeat modes offered by Render, but as an attempt to help
track these down, I've written the attached program.
With a recent Xephyr build I'm seeing the following results:
Testing repeat mode none: PASS
Testing repeat mode normal: PASS
Testing repeat mode pad: *** FAIL ***
57 pixels differ from expected result.
Expected output written to repeat-test-pad-expected.png
Actual output written to repeat-test-pad-out.png
Testing repeat mode reflect: *** FAIL ***
60 pixels differ from expected result.
Expected output written to repeat-test-reflect-expected.png
Actual output written to repeat-test-reflect-out.png
So it looks like there's something still broken in the RepeatPad and
RepeatReflect paths. I believe the reports of failures I've been
getting correlate with problems of RepeatNormal, but hopefully those
are fixed now, (I'll just need to find a version number of an X server
that reliably fixes those).
Reports from this program that show different PASS/FAIL patterns than
the above for various X server configurations might be
interesting. And fixes for the X server/pixman for any of the failures
would also be most appreciated.
I probably should have looked into making this part of rendercheck,
but I haven't done that. Also this doesn't test any transformation
other than an integer offset, (passed directly through a parameter to
XRenderComposite), and leaves the pattern matrix unset, so defaulting
to an identity transformation.
-Carl
[1] cairo xlib buggy_repeat not detected correctly
https://bugzilla.mozilla.org/show_bug.cgi?id=413583
Also, people have reported that cairo's extend-reflect test in the
test suite, (which oddly calls into Render only with RepeatNormal,
not RepeatReflect), causes X server crashes.
-------------- next part --------------
/* gcc -o repeat-test $(pkg-config --cflags --libs xrender cairo-xlib) repeat-test.c */
/* repeat-test
*
* This is a very simple test of the 4 repeat modes made available as
* of version 0.10 of the X render extension. The 4 repeat modes are
* tested with a simple 2x2 source being drawn with an offset to an
* 8x8 destination. No other pattern transformation, (eg. rotation or
* scale), is tested here.
*
* Copyright ? 2007 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Author: Carl Worth <cworth at cworth.org>
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xrender.h>
/* This cairo stuff is strictly optional. It could be easily stripped
* out and the test would still be function. But it does makes it easy
* to view the output. */
#include <cairo-xlib-xrender.h>
#define SIZE 8
#define NUM_REPEAT_MODES (RepeatReflect + 1)
static const char* repeat_mode_name[NUM_REPEAT_MODES] = {
"none" , "normal", "pad", "reflect"
};
#define R 0x00FF0000
#define G 0x0000FF00
#define B 0x000000FF
#define W 0x00FFFFFF
uint32_t expected[NUM_REPEAT_MODES][SIZE * SIZE] = {
{
/* RepeatNone */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, R, G, 0, 0,
0, 0, 0, 0, B, W, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
},
{
/* RepeatNormal */
R, G, R, G, R, G, R, G,
B, W, B, W, B, W, B, W,
R, G, R, G, R, G, R, G,
B, W, B, W, B, W, B, W,
R, G, R, G, R, G, R, G,
B, W, B, W, B, W, B, W,
R, G, R, G, R, G, R, G,
B, W, B, W, B, W, B, W
},
{
/* RepeatPad */
R, R, R, R, R, G, G, G,
R, R, R, R, R, G, G, G,
R, R, R, R, R, G, G, G,
R, R, R, R, R, G, G, G,
R, R, R, R, R, G, G, G,
B, B, B, B, B, W, W, W,
B, B, B, B, B, W, W, W,
B, B, B, B, B, W, W, W
},
{
/* RepeatReflect */
R, G, G, R, R, G, G, R,
B, W, W, B, B, W, W, B,
B, W, W, B, B, W, W, B,
R, G, G, R, R, G, G, R,
R, G, G, R, R, G, G, R,
B, W, W, B, B, W, W, B,
B, W, W, B, B, W, W, B,
R, G, G, R, R, G, G, R
},
};
int
main (void)
{
Display *dpy;
XRenderPictFormat *format;
Pixmap source_pix, dest_pix;
Picture source_pict, dest_pict;
XRenderPictureAttributes pa;
GC gc;
int repeat;
cairo_surface_t *surface;
char *filename;
int x, y, error;
XImage *ximage;
dpy = XOpenDisplay (NULL);
if (dpy == NULL) {
fprintf (stderr, "Error: Failed to open display: %s\n",
XDisplayName(NULL));
return 1;
}
format = XRenderFindStandardFormat (dpy, PictStandardRGB24);
if (format == NULL) {
fprintf (stderr, "Error: X server does not have the Render extension.\n");
return 1;
}
source_pix = XCreatePixmap (dpy, DefaultRootWindow (dpy),
2, 2, format->depth);
dest_pix = XCreatePixmap (dpy, DefaultRootWindow (dpy),
SIZE, SIZE, format->depth);
source_pict = XRenderCreatePicture (dpy, source_pix, format, 0, NULL);
dest_pict = XRenderCreatePicture (dpy, dest_pix, format, 0, NULL);
/* Set Carl's favorite RGBW checkerboard pattern into source. */
gc = XCreateGC (dpy, source_pix, 0, NULL);
XSetForeground (dpy, gc, 0x00ff0000);
XFillRectangle (dpy, source_pix, gc,
0, 0, 1, 1);
XSetForeground (dpy, gc, 0x0000ff00);
XFillRectangle (dpy, source_pix, gc,
1, 0, 1, 1);
XSetForeground (dpy, gc, 0x000000ff);
XFillRectangle (dpy, source_pix, gc,
0, 1, 1, 1);
XSetForeground (dpy, gc, 0x00ffffff);
XFillRectangle (dpy, source_pix, gc,
1, 1, 1, 1);
XFreeGC (dpy, gc);
/* Exercise each render repeat mode. */
for (repeat = RepeatNone; repeat < NUM_REPEAT_MODES; repeat++) {
printf ("Testing repeat mode %s: ", repeat_mode_name[repeat]);
pa.repeat = repeat;
XRenderChangePicture (dpy, source_pict, CPRepeat, &pa);
/* First set the destination to all black. */
gc = XCreateGC (dpy, dest_pix, 0, NULL);
XSetForeground (dpy, gc, 0x00000000);
XFillRectangle (dpy, dest_pix, gc,
0, 0, SIZE, SIZE);
XFreeGC (dpy, gc);
/* Then composite the repeating picture over it. */
XRenderComposite (dpy, PictOpOver,
source_pict, None, dest_pict,
- SIZE / 2, - SIZE /2,
0, 0,
0, 0,
SIZE, SIZE);
/* Verify the result against what's expected. */
error = 0;
ximage = XGetImage (dpy, dest_pix, 0, 0, SIZE, SIZE, AllPlanes, ZPixmap);
for (y=0; y < SIZE; y++)
for (x=0; x < SIZE; x++)
if (XGetPixel (ximage, x, y) != expected[repeat][SIZE * y + x])
error++;
if (error) {
printf ("*** FAIL ***\n\t%d pixels differ from expected result.\n",
error);
surface = cairo_image_surface_create_for_data
((unsigned char *) expected[repeat], CAIRO_FORMAT_RGB24,
SIZE, SIZE, SIZE * 4);
asprintf (&filename, "repeat-test-%s-expected.png",
repeat_mode_name[repeat]);
cairo_surface_write_to_png (surface, filename);
printf ("\tExpected output written to %s\n", filename);
free (filename);
cairo_surface_destroy (surface);
} else {
printf ("PASS\n");
}
surface = cairo_xlib_surface_create_with_xrender_format
(dpy, dest_pix, DefaultScreenOfDisplay (dpy),
format, SIZE, SIZE);
asprintf (&filename, "repeat-test-%s-out.png", repeat_mode_name[repeat]);
cairo_surface_write_to_png (surface, filename);
if (error)
printf ("\tActual output written to %s\n\n", filename);
free (filename);
cairo_surface_destroy (surface);
}
XRenderFreePicture (dpy, source_pict);
XRenderFreePicture (dpy, dest_pict);
XFreePixmap (dpy, source_pix);
XFreePixmap (dpy, dest_pix);
XCloseDisplay (dpy);
return 0;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: <http://lists.x.org/archives/xorg/attachments/20080226/09825c4e/attachment.pgp>
More information about the xorg
mailing list