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