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