plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }