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