#include #include "x11-inc.h" #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; /* only fetch dst data if we need it */ if((par->state&(Simplemask|Fullmask)) != (Simplemask|Fullmask)) _xgetxdata(par->dst, par->r); /* always fetch source and mask */ _xgetxdata(par->src, par->sr); _xgetxdata(par->mask, par->mr); /* now can run memimagedraw on the in-memory bits */ _memimagedraw(par); if(xdraw(par)) return; /* put bits back on x server */ _xputxdata(par->dst, par->r); } static int xdraw(Memdrawparam *par) { u32int sdval; uint m, state; Memimage *dst, *mask; Point dp, mp; Rectangle r; Xmem *xdst, *xmask; XGC gc; if(par->dst->X == nil) return 0; dst = par->dst; mask = par->mask; r = par->r; 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|Fullsrc|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. * * This is disabled because Ubuntu Precise seems to ship with * a buggy X server that sometimes drops the XCopyArea * requests on the floor. m = Simplemask|Fullmask; if((state&(m|Replsrc))==m && src->chan==dst->chan && src->X){ Xmem *xsrc; Point sp; 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? */ return 0; /* 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; }