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