| #include <u.h> |
| #include "x11-inc.h" |
| #include <libc.h> |
| #include <draw.h> |
| #include <memdraw.h> |
| #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 *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|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. |
| */ |
| 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? */ |
| 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; |
| } |
| |