mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-12 11:10:07 +00:00
143 lines
3.3 KiB
C
143 lines
3.3 KiB
C
#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|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;
|
|
}
|
|
|