From 76193d7cb0457807b2f0b95f909ab5de19480cd7 Mon Sep 17 00:00:00 2001 From: rsc Date: Tue, 30 Sep 2003 17:47:42 +0000 Subject: Initial revision --- src/libdraw/x11-draw.c | 143 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 src/libdraw/x11-draw.c (limited to 'src/libdraw/x11-draw.c') diff --git a/src/libdraw/x11-draw.c b/src/libdraw/x11-draw.c new file mode 100644 index 00000000..33b92c87 --- /dev/null +++ b/src/libdraw/x11-draw.c @@ -0,0 +1,143 @@ +#include "x11-inc.h" + +#include +#include +#include +#include +#include "x11-memdraw.h" + +static int xdraw(Memdrawparam*); + +/* + * The X acceleration doesn't fit into the standard hwaccel + * model because we have the extra steps of pulling the image + * data off the server and putting it back when we're done. + */ +void +memimagedraw(Memimage *dst, Rectangle r, Memimage *src, Point sp, + Memimage *mask, Point mp, int op) +{ + Memdrawparam *par; + + if((par = _memimagedrawsetup(dst, r, src, sp, mask, mp, op)) == nil) + return; + + if(xdraw(par)) + return; + + /* only fetch dst data if we need it */ + if((par->state&(Simplemask|Fullmask)) != (Simplemask|Fullmask)) + xgetxdata(dst, par->r); + + /* always fetch source and mask */ + xgetxdata(src, par->sr); + xgetxdata(mask, par->mr); + + /* now can run memimagedraw on the in-memory bits */ + _memimagedraw(par); + + /* put bits back on x server */ + xputxdata(dst, par->r); +} + +static int +xdraw(Memdrawparam *par) +{ + u32int sdval; + uint m, state; + Memimage *src, *dst, *mask; + Point dp, mp, sp; + Rectangle r; + Xmem *xdst, *xmask, *xsrc; + XGC gc; + + if(par->dst->X == nil) + return 0; + + dst = par->dst; + mask = par->mask; + r = par->r; + src = par->src; + state = par->state; + + /* + * If we have an opaque mask and source is one opaque pixel, + * we can convert to the destination format and just XFillRectangle. + */ + m = Simplesrc|Simplemask|Fullmask; + if((state&m) == m){ + xfillcolor(dst, r, par->sdval); + xdirtyxdata(dst, r); + return 1; + } + + /* + * If no source alpha and an opaque mask, we can just copy + * the source onto the destination. If the channels are the + * same and the source is not replicated, XCopyArea works. + */ + m = Simplemask|Fullmask; + if((state&(m|Replsrc))==m && src->chan==dst->chan && src->X){ + xdst = dst->X; + xsrc = src->X; + dp = subpt(r.min, dst->r.min); + sp = subpt(par->sr.min, src->r.min); + gc = dst->chan==GREY1 ? _x.gccopy0 : _x.gccopy; + + XCopyArea(_x.display, xsrc->pixmap, xdst->pixmap, gc, + sp.x, sp.y, Dx(r), Dy(r), dp.x, dp.y); + xdirtyxdata(dst, r); + return 1; + } + + /* + * If no source alpha, a 1-bit mask, and a simple source, + * we can copy through the mask onto the destination. + */ + if(dst->X && mask->X && !(mask->flags&Frepl) + && mask->chan==GREY1 && (state&Simplesrc)){ + xdst = dst->X; + xmask = mask->X; + sdval = par->sdval; + + dp = subpt(r.min, dst->r.min); + mp = subpt(r.min, subpt(par->mr.min, mask->r.min)); + + if(dst->chan == GREY1){ + gc = _x.gcsimplesrc0; + if(_x.gcsimplesrc0color != sdval){ + XSetForeground(_x.display, gc, sdval); + _x.gcsimplesrc0color = sdval; + } + if(_x.gcsimplesrc0pixmap != xmask->pixmap){ + XSetStipple(_x.display, gc, xmask->pixmap); + _x.gcsimplesrc0pixmap = xmask->pixmap; + } + }else{ + /* this doesn't work on rob's mac? */ + gc = _x.gcsimplesrc; + if(dst->chan == CMAP8 && _x.usetable) + sdval = _x.tox11[sdval]; + + if(_x.gcsimplesrccolor != sdval){ + XSetForeground(_x.display, gc, sdval); + _x.gcsimplesrccolor = sdval; + } + if(_x.gcsimplesrcpixmap != xmask->pixmap){ + XSetStipple(_x.display, gc, xmask->pixmap); + _x.gcsimplesrcpixmap = xmask->pixmap; + } + } + XSetTSOrigin(_x.display, gc, mp.x, mp.y); + XFillRectangle(_x.display, xdst->pixmap, gc, dp.x, dp.y, + Dx(r), Dy(r)); + xdirtyxdata(dst, r); + return 1; + } + + /* + * Can't accelerate. + */ + return 0; +} + -- cgit v1.2.3