Gradients for Xrender

Lars Knoll lars at
Mon May 30 10:22:22 PDT 2005


I had some time over the weekend and added support for gradients to render. 

The implementation supports all the gradient types defined in SVG (linear, 
radial and conical). What I've done is to extend Render by one more request:

typedef struct {
    CARD16 type;
    CARD16 spread;
    Fixed x1_or_cx;
    Fixed y1_or_cy;
    Fixed x2_or_fx;
    Fixed y2_or_fy;
    Fixed radius_or_angle;
} xRenderGradient;

typedef struct {
    CARD8	reqType;
    CARD8	renderReqType;
    CARD16 length B16;
    Picture	pid B32;
    xRenderGradient gradient;
    CARD16 numStopPoints;
    CARD16 pad1;
} xRenderCreateGradientReq;

The request maps to the following API on the client side:

typedef struct _XLinearGradient {
    int type;
    int spread;
    XPointFixed p1;
    XPointFixed p2;
} XLinearGradient;

typedef struct _XRadialGradient {
    int type;
    int spread;
    XPointFixed center;
    XPointFixed focus;
    XFixed radius;
} XRadialGradient;

typedef struct _XConicalGradient {
    int type;
    XPointFixed center;
    XFixed angle; /* in degrees */
} XConicalGradient;

typedef union _XGradient {
    int type;
    XLinearGradient linear;
    XRadialGradient radial;
    XConicalGradient conical;
} XGradient;

Picture XRenderCreateGradient (Display *dpy,
                               const XGradient *gradient,
                               const XFixed *stops,
                               const XRenderColor *colors,
                               int nstops);

On the server side (I just implemented it in the kdrive server for now), the 
framebuffer implementation uses the scanline based algorithm in fbcompose.c 
Zack and I implemented some weeks ago. 

The main architectural change in the XServer is that the created picture does 
not have an associated Drawable. It is thus readonly, and some code paths in 
the server need to check now for this case and throw errors in case a Request 
tries to modify such a Picture (the only modifications allowed for the moment 
is setting a transformation on the gradient Picture). 

The reason for doing it this way is that one gets full support for Gradients 
as source/mask pictures in all XRender calls. To the client a gradient is 
just another Picture (though he would get errors if he tried to paint onto 
it), that can be used in all compositing operations and that can be freed 
using XRenderFreePicture. At the same time the gradient is independent of the 
Screen as it doesn't need to hold any data associated with a particular 

The algorithm seems to be reasonably fast. For a full screen (1280x1024) a 
linear gradient takes about 50ms, a radial gradient 130ms and a conical about 
200ms (tested using Xephyr) on my hardware.

You can find the patches against the Render/XRender/xserver repositories and a 
test application at (needs a recent Qt4 

Have fun,

More information about the xorg mailing list