rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 1 | #include <u.h> |
rsc | be22ae2 | 2004-03-26 01:59:35 +0000 | [diff] [blame] | 2 | #include "x11-inc.h" |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 3 | #include <libc.h> |
| 4 | #include <draw.h> |
| 5 | #include <memdraw.h> |
| 6 | #include "x11-memdraw.h" |
| 7 | |
| 8 | /* |
| 9 | * Allocate a Memimage with an optional pixmap backing on the X server. |
| 10 | */ |
| 11 | Memimage* |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 12 | _xallocmemimage(Rectangle r, u32int chan, int pixmap) |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 13 | { |
| 14 | int d, offset; |
| 15 | Memimage *m; |
| 16 | Xmem *xm; |
| 17 | XImage *xi; |
| 18 | |
| 19 | m = _allocmemimage(r, chan); |
| 20 | if(chan != GREY1 && chan != _x.chan) |
| 21 | return m; |
rsc | e290cfc | 2004-06-09 14:11:47 +0000 | [diff] [blame] | 22 | if(_x.display == 0) |
| 23 | return m; |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 24 | |
| 25 | /* |
| 26 | * For bootstrapping, don't bother storing 1x1 images |
| 27 | * on the X server. Memimageinit needs to allocate these |
| 28 | * and we memimageinit before we do the rest of the X stuff. |
| 29 | * Of course, 1x1 images on the server are useless anyway. |
| 30 | */ |
| 31 | if(Dx(r)==1 && Dy(r)==1) |
| 32 | return m; |
| 33 | |
| 34 | xm = mallocz(sizeof(Xmem), 1); |
| 35 | if(xm == nil){ |
| 36 | freememimage(m); |
| 37 | return nil; |
| 38 | } |
| 39 | |
| 40 | /* |
rsc | 161060a | 2003-10-11 02:47:43 +0000 | [diff] [blame] | 41 | * Allocate backing store. |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 42 | */ |
rsc | 161060a | 2003-10-11 02:47:43 +0000 | [diff] [blame] | 43 | if(chan == GREY1) |
| 44 | d = 1; |
| 45 | else |
| 46 | d = _x.depth; |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 47 | if(pixmap != PMundef) |
| 48 | xm->pixmap = pixmap; |
| 49 | else |
rsc | 161060a | 2003-10-11 02:47:43 +0000 | [diff] [blame] | 50 | xm->pixmap = XCreatePixmap(_x.display, _x.drawable, Dx(r), Dy(r), d); |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 51 | |
| 52 | /* |
| 53 | * We want to align pixels on word boundaries. |
| 54 | */ |
rsc | 161060a | 2003-10-11 02:47:43 +0000 | [diff] [blame] | 55 | if(m->depth == 24) |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 56 | offset = r.min.x&3; |
| 57 | else |
| 58 | offset = r.min.x&(31/m->depth); |
| 59 | r.min.x -= offset; |
| 60 | assert(wordsperline(r, m->depth) <= m->width); |
| 61 | |
| 62 | /* |
| 63 | * Wrap our data in an XImage structure. |
| 64 | */ |
rsc | 161060a | 2003-10-11 02:47:43 +0000 | [diff] [blame] | 65 | xi = XCreateImage(_x.display, _x.vis, d, |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 66 | ZPixmap, 0, (char*)m->data->bdata, Dx(r), Dy(r), |
| 67 | 32, m->width*sizeof(u32int)); |
| 68 | if(xi == nil){ |
| 69 | freememimage(m); |
| 70 | if(xm->pixmap != pixmap) |
| 71 | XFreePixmap(_x.display, xm->pixmap); |
| 72 | return nil; |
| 73 | } |
| 74 | |
| 75 | xm->xi = xi; |
| 76 | xm->r = r; |
| 77 | |
| 78 | /* |
| 79 | * Set the XImage parameters so that it looks exactly like |
| 80 | * a Memimage -- we're using the same data. |
| 81 | */ |
| 82 | if(m->depth < 8 || m->depth == 24) |
| 83 | xi->bitmap_unit = 8; |
| 84 | else |
| 85 | xi->bitmap_unit = m->depth; |
| 86 | xi->byte_order = LSBFirst; |
| 87 | xi->bitmap_bit_order = MSBFirst; |
| 88 | xi->bitmap_pad = 32; |
| 89 | XInitImage(xi); |
| 90 | XFlush(_x.display); |
| 91 | |
| 92 | m->X = xm; |
| 93 | return m; |
| 94 | } |
| 95 | |
| 96 | Memimage* |
| 97 | allocmemimage(Rectangle r, u32int chan) |
| 98 | { |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 99 | return _xallocmemimage(r, chan, PMundef); |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 100 | } |
| 101 | |
| 102 | void |
| 103 | freememimage(Memimage *m) |
| 104 | { |
| 105 | Xmem *xm; |
| 106 | |
| 107 | if(m == nil) |
| 108 | return; |
| 109 | |
| 110 | xm = m->X; |
| 111 | if(xm && m->data->ref == 1){ |
| 112 | if(xm->xi){ |
| 113 | xm->xi->data = nil; |
| 114 | XFree(xm->xi); |
| 115 | } |
| 116 | XFreePixmap(_x.display, xm->pixmap); |
| 117 | free(xm); |
| 118 | m->X = nil; |
| 119 | } |
| 120 | _freememimage(m); |
| 121 | } |
| 122 | |