Question about XRender specification

Carl Worth cworth at cworth.org
Tue Apr 8 14:36:42 PDT 2008


On Tue, 08 Apr 2008 17:21:49 -0400, Peter Harris wrote:
> Helge Bahmann wrote:
> >> 				XRenderCompositeTrapezoids(display,
> >> 					PictOpOver, red_transp, picture, 0,
> >> 					0, 0, &trap, 2);
> >
> > the way you are calling, they are drawn independently, this means the first
> > trapezoid covers the pixel by 1/2, the second gets drawn over and now the
> > pixel is covered by 3/4 and NOT 1 !

No. The XRenderCompositeTrapezoids call pre-composes the trapezoids
together into a single mask, (with ADD I believe), and the uses that
as the mask for the Over operation being asked for here.

> > The solution is to use PictOpDisjointOver; possibly to have to composite your
> > figure into a temporary mask and then use this pre-composited shape in a
> > second rendering step

The XRenderAddTraps call can be used if you want to have an explicit
temporary mask, (though note that it uses a different trapezoid
specification, and also Keith just very recently fixed some bugs in
it). I don't think PictOpDisjointOver should ever be necessary,
(indeed, trapezoid rendering existed before that operator ever
did). But yes, it probably would work.

> Alternatively, you could specify a maskFormat other than NULL when you
> call XRenderCompositeTrapezoids.

That 0 there is odd, and I assume it must be a bug.

But even with that I wasn't able to replicate the original reported
behavior.

I've attached my working program below. It uses an A8 format for the
maskFormat and I get seamless rendering with antialiasing on the outer
edges. If I use 0 there, I still get seamless rendering, but
non-antialiased outer edges, (which is what I would expect for an A1
format, so maybe that is what the 0 is being interpreted as).

Clemens, is there something very different in your test case compared
to mine?

-Carl

PS. Ouch, it sure is painful to write programs that draw with Xrender
directly. I'm glad that I've got cairo to take care of these details
for me.

-------------- next part --------------
/* gcc -o argb_demo argb_demo.c -L/usr/X11R6/lib -lXrender -lX11 */
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xrender.h>

#define WIDTH_DEFAULT 200
#define HEIGHT_DEFAULT 100

/* Naming a window shouldn't require specifying width/height, but
 * that's what Xlib makes us do here. */
static void
name_window (Display *dpy, Window win, int width, int height,
	     const char *name)
{
    XSizeHints *size_hints;
    XWMHints *wm_hints;
    XClassHint *class_hint;

    size_hints = XAllocSizeHints ();
    size_hints->flags = 0;
    size_hints->x = 0;
    size_hints->y = 0;
    size_hints->width = width;
    size_hints->height = height;

    wm_hints = XAllocWMHints ();
    wm_hints->flags = InputHint;
    wm_hints->input = True;

    class_hint = XAllocClassHint ();
    class_hint->res_name  = "argb-demo";
    class_hint->res_class = "ARGB-demo";

    Xutf8SetWMProperties (dpy, win, name, name, 0, 0,
			  size_hints, wm_hints, class_hint);
    XFree (size_hints);
    XFree (wm_hints);
    XFree (class_hint);
}

static void
draw (Display *dpy, Window win, Visual *visual,
      unsigned int width, unsigned int height)
{
    int off;
    XTrapezoid trap[2];
    Pixmap source_pix;
    Picture source, dest;
    XRenderPictureAttributes source_attr;
    XRenderColor red;
    XRenderPictFormat *rgb24_format, *a8_format;

    rgb24_format = XRenderFindStandardFormat (dpy, PictStandardRGB24);
    a8_format = XRenderFindStandardFormat (dpy, PictStandardA8);

    XClearWindow (dpy, win);

    source_attr.repeat = RepeatNormal;
    source_pix = XCreatePixmap (dpy, win, 1, 1, rgb24_format->depth);
    source = XRenderCreatePicture (dpy, source_pix,
				   rgb24_format,
				   CPRepeat, &source_attr);
    red.red   = 0xffff;
    red.green = 0;
    red.blue  = 0;
    red.alpha = 0xffff;
    XRenderFillRectangle (dpy, PictOpSrc, source, &red,
			  0, 0, 1, 1);

    dest = XRenderCreatePicture (dpy, win,
				 XRenderFindVisualFormat (dpy, visual),
				 0, NULL);

    trap[0].top=10<<16;
    trap[0].bottom=80<<16;
    trap[0].left.p1.x=30<<16; trap[0].left.p1.y=0<<16;
    trap[0].left.p2.x=20<<16; trap[0].left.p2.y=90<<16;
    trap[0].right.p1.x=XDoubleToFixed(100); trap[0].right.p1.y=0<<16;
    trap[0].right.p2.x=XDoubleToFixed(90); trap[0].right.p2.y=90<<16;

    trap[1].top=XDoubleToFixed(10);
    trap[1].bottom=80<<16;
    trap[1].left.p1.x=XDoubleToFixed(100); trap[1].left.p1.y=0<<16;
    trap[1].left.p2.x=XDoubleToFixed(90); trap[1].left.p2.y=90<<16;
    trap[1].right.p1.x=160<<16; trap[1].right.p1.y=0<<16;
    trap[1].right.p2.x=150<<16; trap[1].right.p2.y=90<<16;

    XRenderCompositeTrapezoids(dpy,
			       PictOpOver,
			       source, dest, a8_format,
			       0, 0, trap, 2);

    XRenderFreePicture (dpy, dest);
    XRenderFreePicture (dpy, source);
    XFreePixmap (dpy, source_pix);
}

int
main(void)
{
    Display *dpy;
    int scr;
    Window win, root;
    Visual *visual;
    XSetWindowAttributes wattr;
    unsigned long wmask;
    unsigned int width  = WIDTH_DEFAULT;
    unsigned int height = HEIGHT_DEFAULT;
    int needs_redraw;

    dpy = XOpenDisplay (0);
    if (dpy == NULL) {
	fprintf(stderr, "Failed to open display: %s\n", XDisplayName(0));
	return 1;
    }

    scr = DefaultScreen (dpy);
    root = RootWindow (dpy, scr);
    visual = DefaultVisual (dpy, scr);

    wattr.event_mask = ExposureMask | StructureNotifyMask;
    wattr.background_pixel = transparent;
    wattr.border_pixel = 0;
    wattr.colormap = XCreateColormap (dpy, root, visual, AllocNone);
    wmask = CWEventMask | CWBackPixel | CWBorderPixel | CWColormap;

    win = XCreateWindow (dpy, root, 0, 0, width, height, 0,
			 DefaultDepth (dpy, scr),
			 InputOutput, visual, wmask, &wattr);

    name_window (dpy, win, width, height, "Trap test");

    XSelectInput (dpy, win, KeyPressMask | StructureNotifyMask | ExposureMask);

    XMapWindow (dpy, win);

    needs_redraw = 1;

    while (1) {
	XEvent xev;

	if (! XPending (dpy) && needs_redraw) {
	    draw (dpy, win, visual, width, height);
	    needs_redraw = 0;
	}

	XNextEvent (dpy, &xev);

	/* Quit on key press. */
	switch (xev.xany.type) {
	case KeyPress:
	    goto DONE;
	case ConfigureNotify:
	    width = xev.xconfigure.width;
	    height = xev.xconfigure.height;
	    /* fall-through */
	default:
	    needs_redraw = 1;
	}
    }
    DONE:

    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/20080408/e97e7aac/attachment.pgp>


More information about the xorg mailing list