| #include <u.h> |
| #include "x11-inc.h" |
| #include <libc.h> |
| #include <draw.h> |
| #include <memdraw.h> |
| #include "x11-memdraw.h" |
| |
| AUTOLIB(X11); |
| |
| /* |
| * 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; |
| if(_x.display == 0) |
| 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. |
| */ |
| if(chan == GREY1) |
| d = 1; |
| else |
| d = _x.depth; |
| if(pixmap != PMundef) |
| xm->pixmap = pixmap; |
| else |
| xm->pixmap = XCreatePixmap(_x.display, _x.drawable, Dx(r), Dy(r), d); |
| |
| /* |
| * We want to align pixels on word boundaries. |
| */ |
| if(m->depth == 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, |
| 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); |
| } |
| |