diff options
Diffstat (limited to 'src/libdraw/x11-alloc.c')
-rw-r--r-- | src/libdraw/x11-alloc.c | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/src/libdraw/x11-alloc.c b/src/libdraw/x11-alloc.c new file mode 100644 index 00000000..19475c74 --- /dev/null +++ b/src/libdraw/x11-alloc.c @@ -0,0 +1,120 @@ +#include "x11-inc.h" + +#include <u.h> +#include <libc.h> +#include <draw.h> +#include <memdraw.h> +#include "x11-memdraw.h" + +/* + * Allocate a Memimage with an optional pixmap backing on the X server. + */ +Memimage* +xallocmemimage(Rectangle r, u32int chan, int pixmap) +{ + int d, offset; + Memimage *m; + Xmem *xm; + XImage *xi; + + m = _allocmemimage(r, chan); + if(chan != GREY1 && chan != _x.chan) + return m; + + /* + * For bootstrapping, don't bother storing 1x1 images + * on the X server. Memimageinit needs to allocate these + * and we memimageinit before we do the rest of the X stuff. + * Of course, 1x1 images on the server are useless anyway. + */ + if(Dx(r)==1 && Dy(r)==1) + return m; + + xm = mallocz(sizeof(Xmem), 1); + if(xm == nil){ + freememimage(m); + return nil; + } + + /* + * Allocate backing store. What we call a 32-bit image + * the X server calls a 24-bit image. + */ + d = m->depth; + if(pixmap != PMundef) + xm->pixmap = pixmap; + else + xm->pixmap = XCreatePixmap(_x.display, _x.drawable, + Dx(r), Dy(r), d==32 ? 24 : d); + + /* + * We want to align pixels on word boundaries. + */ + if(d == 24) + offset = r.min.x&3; + else + offset = r.min.x&(31/m->depth); + r.min.x -= offset; + assert(wordsperline(r, m->depth) <= m->width); + + /* + * Wrap our data in an XImage structure. + */ + xi = XCreateImage(_x.display, _x.vis, d==32 ? 24 : d, + ZPixmap, 0, (char*)m->data->bdata, Dx(r), Dy(r), + 32, m->width*sizeof(u32int)); + if(xi == nil){ + freememimage(m); + if(xm->pixmap != pixmap) + XFreePixmap(_x.display, xm->pixmap); + return nil; + } + + xm->xi = xi; + xm->r = r; + + /* + * Set the XImage parameters so that it looks exactly like + * a Memimage -- we're using the same data. + */ + if(m->depth < 8 || m->depth == 24) + xi->bitmap_unit = 8; + else + xi->bitmap_unit = m->depth; + xi->byte_order = LSBFirst; + xi->bitmap_bit_order = MSBFirst; + xi->bitmap_pad = 32; + XInitImage(xi); + XFlush(_x.display); + + m->X = xm; + return m; +} + +Memimage* +allocmemimage(Rectangle r, u32int chan) +{ + return xallocmemimage(r, chan, PMundef); +} + +void +freememimage(Memimage *m) +{ + Xmem *xm; + + if(m == nil) + return; + + xm = m->X; + if(xm && m->data->ref == 1){ + if(xm->xi){ + xm->xi->data = nil; + XFree(xm->xi); + } + XFreePixmap(_x.display, xm->pixmap); + free(xm); + m->X = nil; + } + _freememimage(m); +} + |