Blob


1 #include "x11-inc.h"
3 #include <u.h>
4 #include <libc.h>
5 #include <draw.h>
6 #include <memdraw.h>
7 #include "x11-memdraw.h"
9 static int xdraw(Memdrawparam*);
11 /*
12 * The X acceleration doesn't fit into the standard hwaccel
13 * model because we have the extra steps of pulling the image
14 * data off the server and putting it back when we're done.
15 */
16 void
17 memimagedraw(Memimage *dst, Rectangle r, Memimage *src, Point sp,
18 Memimage *mask, Point mp, int op)
19 {
20 Memdrawparam *par;
22 if((par = _memimagedrawsetup(dst, r, src, sp, mask, mp, op)) == nil)
23 return;
25 /* only fetch dst data if we need it */
26 if((par->state&(Simplemask|Fullmask)) != (Simplemask|Fullmask))
27 xgetxdata(dst, par->r);
29 /* always fetch source and mask */
30 xgetxdata(src, par->sr);
31 xgetxdata(mask, par->mr);
33 /* now can run memimagedraw on the in-memory bits */
34 _memimagedraw(par);
36 if(xdraw(par))
37 return;
39 /* put bits back on x server */
40 xputxdata(dst, par->r);
41 }
43 static int
44 xdraw(Memdrawparam *par)
45 {
46 u32int sdval;
47 uint m, state;
48 Memimage *src, *dst, *mask;
49 Point dp, mp, sp;
50 Rectangle r;
51 Xmem *xdst, *xmask, *xsrc;
52 XGC gc;
54 if(par->dst->X == nil)
55 return 0;
57 dst = par->dst;
58 mask = par->mask;
59 r = par->r;
60 src = par->src;
61 state = par->state;
63 /*
64 * If we have an opaque mask and source is one opaque pixel,
65 * we can convert to the destination format and just XFillRectangle.
66 */
67 m = Simplesrc|Simplemask|Fullmask;
68 if((state&m) == m){
69 xfillcolor(dst, r, par->sdval);
70 // xdirtyxdata(dst, r);
71 return 1;
72 }
74 /*
75 * If no source alpha and an opaque mask, we can just copy
76 * the source onto the destination. If the channels are the
77 * same and the source is not replicated, XCopyArea works.
78 */
79 m = Simplemask|Fullmask;
80 if((state&(m|Replsrc))==m && src->chan==dst->chan && src->X){
81 xdst = dst->X;
82 xsrc = src->X;
83 dp = subpt(r.min, dst->r.min);
84 sp = subpt(par->sr.min, src->r.min);
85 gc = dst->chan==GREY1 ? _x.gccopy0 : _x.gccopy;
87 XCopyArea(_x.display, xsrc->pixmap, xdst->pixmap, gc,
88 sp.x, sp.y, Dx(r), Dy(r), dp.x, dp.y);
89 // xdirtyxdata(dst, r);
90 return 1;
91 }
93 /*
94 * If no source alpha, a 1-bit mask, and a simple source,
95 * we can copy through the mask onto the destination.
96 */
97 if(dst->X && mask->X && !(mask->flags&Frepl)
98 && mask->chan==GREY1 && (state&Simplesrc)){
99 xdst = dst->X;
100 xmask = mask->X;
101 sdval = par->sdval;
103 dp = subpt(r.min, dst->r.min);
104 mp = subpt(r.min, subpt(par->mr.min, mask->r.min));
106 if(dst->chan == GREY1){
107 gc = _x.gcsimplesrc0;
108 if(_x.gcsimplesrc0color != sdval){
109 XSetForeground(_x.display, gc, sdval);
110 _x.gcsimplesrc0color = sdval;
112 if(_x.gcsimplesrc0pixmap != xmask->pixmap){
113 XSetStipple(_x.display, gc, xmask->pixmap);
114 _x.gcsimplesrc0pixmap = xmask->pixmap;
116 }else{
117 /* this doesn't work on rob's mac? */
118 return 0;
119 gc = _x.gcsimplesrc;
120 if(dst->chan == CMAP8 && _x.usetable)
121 sdval = _x.tox11[sdval];
123 if(_x.gcsimplesrccolor != sdval){
124 XSetForeground(_x.display, gc, sdval);
125 _x.gcsimplesrccolor = sdval;
127 if(_x.gcsimplesrcpixmap != xmask->pixmap){
128 XSetStipple(_x.display, gc, xmask->pixmap);
129 _x.gcsimplesrcpixmap = xmask->pixmap;
132 XSetTSOrigin(_x.display, gc, mp.x, mp.y);
133 XFillRectangle(_x.display, xdst->pixmap, gc, dp.x, dp.y,
134 Dx(r), Dy(r));
135 // xdirtyxdata(dst, r);
136 return 1;
139 /*
140 * Can't accelerate.
141 */
142 return 0;