Gradients for Xrender
Lars Knoll
lars at trolltech.com
Mon May 30 10:22:22 PDT 2005
Hi,
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
screen.
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
http://trolls.troll.no/lars/xgradients/Render.diff
http://trolls.troll.no/lars/xgradients/Xrender.diff
http://trolls.troll.no/lars/xgradients/xserver.diff
http://trolls.troll.no/lars/xgradients/gradient_test.tgz (needs a recent Qt4
snapshot)
Have fun,
Lars
More information about the xorg
mailing list