1 #include <u.h> 2 #include <libc.h> 3 #include <draw.h> 4 #include <memdraw.h> 5 #include <pool.h> 6 7 void 8 memimagemove(void *from, void *to) 9 { 10 Memdata *md; 11 12 md = *(Memdata**)to; 13 if(md->base != from){ 14 print("compacted data not right: #%p\n", md->base); 15 abort(); 16 } 17 md->base = to; 18 19 /* if allocmemimage changes this must change too */ 20 md->bdata = (uchar*)&md->base[2]; 21 } 22 23 Memimage* 24 allocmemimaged(Rectangle r, ulong chan, Memdata *md) 25 { 26 int d; 27 ulong l; 28 Memimage *i; 29 30 if(Dx(r) <= 0 || Dy(r) <= 0){ 31 werrstr("bad rectangle %R", r); 32 return nil; 33 } 34 if((d = chantodepth(chan)) == 0) { 35 werrstr("bad channel descriptor %.8lux", chan); 36 return nil; 37 } 38 39 l = wordsperline(r, d); 40 41 i = mallocz(sizeof(Memimage), 1); 42 if(i == nil) 43 return nil; 44 45 i->data = md; 46 i->zero = sizeof(ulong)*l*r.min.y; 47 48 if(r.min.x >= 0) 49 i->zero += (r.min.x*d)/8; 50 else 51 i->zero -= (-r.min.x*d+7)/8; 52 i->zero = -i->zero; 53 i->width = l; 54 i->r = r; 55 i->clipr = r; 56 i->flags = 0; 57 i->layer = nil; 58 i->cmap = memdefcmap; 59 if(memsetchan(i, chan) < 0){ 60 free(i); 61 return nil; 62 } 63 return i; 64 } 65 66 Memimage* 67 allocmemimage(Rectangle r, ulong chan) 68 { 69 int d; 70 ulong l, nw; 71 Memdata *md; 72 Memimage *i; 73 74 if((d = chantodepth(chan)) == 0) { 75 werrstr("bad channel descriptor %.8lux", chan); 76 return nil; 77 } 78 79 l = wordsperline(r, d); 80 nw = l*Dy(r); 81 md = malloc(sizeof(Memdata)); 82 if(md == nil) 83 return nil; 84 85 md->ref = 1; 86 md->base = poolalloc(imagmem, (2+nw)*sizeof(ulong)); 87 if(md->base == nil){ 88 free(md); 89 return nil; 90 } 91 92 md->base[0] = (ulong)md; 93 md->base[1] = getcallerpc(&r); 94 95 /* if this changes, memimagemove must change too */ 96 md->bdata = (uchar*)&md->base[2]; 97 98 md->allocd = 1; 99 100 i = allocmemimaged(r, chan, md); 101 if(i == nil){ 102 poolfree(imagmem, md->base); 103 free(md); 104 return nil; 105 } 106 md->imref = i; 107 return i; 108 } 109 110 void 111 freememimage(Memimage *i) 112 { 113 if(i == nil) 114 return; 115 if(i->data->ref-- == 1 && i->data->allocd){ 116 if(i->data->base) 117 poolfree(imagmem, i->data->base); 118 free(i->data); 119 } 120 free(i); 121 } 122 123 /* 124 * Wordaddr is deprecated. 125 */ 126 ulong* 127 wordaddr(Memimage *i, Point p) 128 { 129 return (ulong*) ((ulong)byteaddr(i, p) & ~(sizeof(ulong)-1)); 130 } 131 132 uchar* 133 byteaddr(Memimage *i, Point p) 134 { 135 uchar *a; 136 137 a = i->data->bdata+i->zero+sizeof(ulong)*p.y*i->width; 138 139 if(i->depth < 8){ 140 /* 141 * We need to always round down, 142 * but C rounds toward zero. 143 */ 144 int np; 145 np = 8/i->depth; 146 if(p.x < 0) 147 return a+(p.x-np+1)/np; 148 else 149 return a+p.x/np; 150 } 151 else 152 return a+p.x*(i->depth/8); 153 } 154 155 int 156 memsetchan(Memimage *i, ulong chan) 157 { 158 int d; 159 int t, j, k; 160 ulong cc; 161 int bytes; 162 163 if((d = chantodepth(chan)) == 0) { 164 werrstr("bad channel descriptor"); 165 return -1; 166 } 167 168 i->depth = d; 169 i->chan = chan; 170 i->flags &= ~(Fgrey|Falpha|Fcmap|Fbytes); 171 bytes = 1; 172 for(cc=chan, j=0, k=0; cc; j+=NBITS(cc), cc>>=8, k++){ 173 t=TYPE(cc); 174 if(t < 0 || t >= NChan){ 175 werrstr("bad channel string"); 176 return -1; 177 } 178 if(t == CGrey) 179 i->flags |= Fgrey; 180 if(t == CAlpha) 181 i->flags |= Falpha; 182 if(t == CMap && i->cmap == nil){ 183 i->cmap = memdefcmap; 184 i->flags |= Fcmap; 185 } 186 187 i->shift[t] = j; 188 i->mask[t] = (1<<NBITS(cc))-1; 189 i->nbits[t] = NBITS(cc); 190 if(NBITS(cc) != 8) 191 bytes = 0; 192 } 193 i->nchan = k; 194 if(bytes) 195 i->flags |= Fbytes; 196 return 0; 197 } 198