#include #include #include #include #include "xmem.h" /* perfect approximation to NTSC = .299r+.587g+.114b when 0 ≤ r,g,b < 256 */ #define RGB2K(r,g,b) ((156763*(r)+307758*(g)+59769*(b))>>19) Memimage* xallocmemimage(Rectangle r, ulong chan, int pmid) { Memimage *m; Xmem *xm; XImage *xi; int offset; int d; m = _allocmemimage(r, chan); if(chan != GREY1 && chan != xscreenchan) return m; d = m->depth; xm = mallocz(sizeof(Xmem), 1); if(pmid != PMundef) xm->pmid = pmid; else xm->pmid = XCreatePixmap(xdisplay, xscreenid, Dx(r), Dy(r), (d==32) ? 24 : d); if(m->depth == 24) offset = r.min.x&(4-1); else offset = r.min.x&(31/m->depth); r.min.x -= offset; assert(wordsperline(r, m->depth) <= m->width); xi = XCreateImage(xdisplay, xvis, m->depth==32?24:m->depth, ZPixmap, 0, (char*)m->data->bdata, Dx(r), Dy(r), 32, m->width*sizeof(ulong)); if(xi == nil){ _freememimage(m); return nil; } xm->xi = xi; xm->pc = getcallerpc(&r); xm->r = r; /* * Set the parameters of the XImage so its memory looks exactly like a * Memimage, so we can call _memimagedraw on the same data. All frame * buffers we've seen, and Plan 9's graphics code, require big-endian * bits within bytes, but little endian byte order within pixels. */ xi->bitmap_unit = m->depth < 8 || m->depth == 24 ? 8 : m->depth; xi->byte_order = LSBFirst; xi->bitmap_bit_order = MSBFirst; xi->bitmap_pad = 32; xm->r = Rect(0,0,0,0); XInitImage(xi); XFlush(xdisplay); m->X = xm; return m; } Memimage* allocmemimage(Rectangle r, ulong chan) { return xallocmemimage(r, chan, PMundef); } void freememimage(Memimage *m) { Xmem *xm; if(m == nil) return; if(m->data->ref == 1){ if((xm = m->X) != nil){ if(xm->xi){ xm->xi->data = nil; XFree(xm->xi); } XFreePixmap(xdisplay, xm->pmid); free(xm); m->X = nil; } } _freememimage(m); } void memfillcolor(Memimage *m, ulong val) { _memfillcolor(m, val); if(m->X){ if((val & 0xFF) == 0xFF) xfillcolor(m, m->r, _rgbatoimg(m, val)); else putXdata(m, m->r); } } static void addrect(Rectangle *rp, Rectangle r) { if(rp->min.x >= rp->max.x) *rp = r; else combinerect(rp, r); } XImage* getXdata(Memimage *m, Rectangle r) { uchar *p; int x, y; Xmem *xm; Point xdelta, delta; Point tp; xm = m->X; if(xm == nil) return nil; assert(xm != nil && xm->xi != nil); if(xm->dirty == 0) return xm->xi; r = xm->dirtyr; if(Dx(r)==0 || Dy(r)==0) return xm->xi; delta = subpt(r.min, m->r.min); tp = xm->r.min; /* avoid unaligned access on digital unix */ xdelta = subpt(r.min, tp); XGetSubImage(xdisplay, xm->pmid, delta.x, delta.y, Dx(r), Dy(r), AllPlanes, ZPixmap, xm->xi, xdelta.x, xdelta.y); if(xtblbit && m->chan == CMAP8) for(y=r.min.y; ydirty = 0; xm->dirtyr = Rect(0,0,0,0); return xm->xi; } void putXdata(Memimage *m, Rectangle r) { Xmem *xm; XImage *xi; GC g; int offset; Point xdelta, delta; Point tp; int x, y; uchar *p; xm = m->X; if(xm == nil) return; assert(xm != nil); assert(xm->xi != nil); xi = xm->xi; g = (m->chan == GREY1) ? xgccopy0 : xgccopy; if(m->depth == 24) offset = r.min.x % 4; else offset = m->r.min.x & (31/m->depth); delta = subpt(r.min, m->r.min); tp = xm->r.min; /* avoid unaligned access on digital unix */ xdelta = subpt(r.min, tp); if(xtblbit && m->chan == CMAP8) for(y=r.min.y; ypmid, g, xi, xdelta.x, xdelta.y, delta.x, delta.y, Dx(r), Dy(r)); if(xtblbit && m->chan == CMAP8) for(y=r.min.y; yX) != nil){ xm->dirty = 1; addrect(&xm->dirtyr, r); } }