xref: /plan9/sys/src/cmd/unix/drawterm/libmemdraw/alloc.c (revision ec59a3ddbfceee0efe34584c2c9981a5e5ff1ec4)
18ccd4a63SDavid du Colombier #include <u.h>
28ccd4a63SDavid du Colombier #include <libc.h>
38ccd4a63SDavid du Colombier #include <draw.h>
48ccd4a63SDavid du Colombier #include <memdraw.h>
57dd7cddfSDavid du Colombier 
68ccd4a63SDavid du Colombier #define poolalloc(a, b) malloc(b)
78ccd4a63SDavid du Colombier #define poolfree(a, b) free(b)
87dd7cddfSDavid du Colombier 
97dd7cddfSDavid du Colombier void
memimagemove(void * from,void * to)107dd7cddfSDavid du Colombier memimagemove(void *from, void *to)
117dd7cddfSDavid du Colombier {
127dd7cddfSDavid du Colombier 	Memdata *md;
137dd7cddfSDavid du Colombier 
147dd7cddfSDavid du Colombier 	md = *(Memdata**)to;
157dd7cddfSDavid du Colombier 	if(md->base != from){
167dd7cddfSDavid du Colombier 		print("compacted data not right: #%p\n", md->base);
177dd7cddfSDavid du Colombier 		abort();
187dd7cddfSDavid du Colombier 	}
197dd7cddfSDavid du Colombier 	md->base = to;
207dd7cddfSDavid du Colombier 
217dd7cddfSDavid du Colombier 	/* if allocmemimage changes this must change too */
22*ec59a3ddSDavid du Colombier 	md->bdata = (uchar*)md->base+sizeof(Memdata*)+sizeof(ulong);
237dd7cddfSDavid du Colombier }
247dd7cddfSDavid du Colombier 
257dd7cddfSDavid du Colombier Memimage*
allocmemimaged(Rectangle r,ulong chan,Memdata * md,void * X)267dd7cddfSDavid du Colombier allocmemimaged(Rectangle r, ulong chan, Memdata *md, void *X)
277dd7cddfSDavid du Colombier {
287dd7cddfSDavid du Colombier 	int d;
297dd7cddfSDavid du Colombier 	ulong l;
307dd7cddfSDavid du Colombier 	Memimage *i;
317dd7cddfSDavid du Colombier 
328ccd4a63SDavid du Colombier 	if(Dx(r) <= 0 || Dy(r) <= 0){
338ccd4a63SDavid du Colombier 		werrstr("bad rectangle %R", r);
348ccd4a63SDavid du Colombier 		return nil;
358ccd4a63SDavid du Colombier 	}
367dd7cddfSDavid du Colombier 	if((d = chantodepth(chan)) == 0) {
377dd7cddfSDavid du Colombier 		werrstr("bad channel descriptor %.8lux", chan);
387dd7cddfSDavid du Colombier 		return nil;
397dd7cddfSDavid du Colombier 	}
407dd7cddfSDavid du Colombier 
417dd7cddfSDavid du Colombier 	l = wordsperline(r, d);
427dd7cddfSDavid du Colombier 
438ccd4a63SDavid du Colombier 	i = mallocz(sizeof(Memimage), 1);
447dd7cddfSDavid du Colombier 	if(i == nil)
457dd7cddfSDavid du Colombier 		return nil;
467dd7cddfSDavid du Colombier 
478ccd4a63SDavid du Colombier 	i->X = X;
487dd7cddfSDavid du Colombier 	i->data = md;
497dd7cddfSDavid du Colombier 	i->zero = sizeof(ulong)*l*r.min.y;
507dd7cddfSDavid du Colombier 
517dd7cddfSDavid du Colombier 	if(r.min.x >= 0)
527dd7cddfSDavid du Colombier 		i->zero += (r.min.x*d)/8;
537dd7cddfSDavid du Colombier 	else
547dd7cddfSDavid du Colombier 		i->zero -= (-r.min.x*d+7)/8;
557dd7cddfSDavid du Colombier 	i->zero = -i->zero;
567dd7cddfSDavid du Colombier 	i->width = l;
577dd7cddfSDavid du Colombier 	i->r = r;
587dd7cddfSDavid du Colombier 	i->clipr = r;
597dd7cddfSDavid du Colombier 	i->flags = 0;
607dd7cddfSDavid du Colombier 	i->layer = nil;
617dd7cddfSDavid du Colombier 	i->cmap = memdefcmap;
627dd7cddfSDavid du Colombier 	if(memsetchan(i, chan) < 0){
637dd7cddfSDavid du Colombier 		free(i);
647dd7cddfSDavid du Colombier 		return nil;
657dd7cddfSDavid du Colombier 	}
667dd7cddfSDavid du Colombier 	return i;
677dd7cddfSDavid du Colombier }
687dd7cddfSDavid du Colombier 
697dd7cddfSDavid du Colombier Memimage*
_allocmemimage(Rectangle r,ulong chan)707dd7cddfSDavid du Colombier _allocmemimage(Rectangle r, ulong chan)
717dd7cddfSDavid du Colombier {
727dd7cddfSDavid du Colombier 	int d;
73*ec59a3ddSDavid du Colombier 	u32int l, nw;
74*ec59a3ddSDavid du Colombier 	uchar *p;
757dd7cddfSDavid du Colombier 	Memdata *md;
767dd7cddfSDavid du Colombier 	Memimage *i;
777dd7cddfSDavid du Colombier 
787dd7cddfSDavid du Colombier 	if((d = chantodepth(chan)) == 0) {
797dd7cddfSDavid du Colombier 		werrstr("bad channel descriptor %.8lux", chan);
807dd7cddfSDavid du Colombier 		return nil;
817dd7cddfSDavid du Colombier 	}
827dd7cddfSDavid du Colombier 
837dd7cddfSDavid du Colombier 	l = wordsperline(r, d);
847dd7cddfSDavid du Colombier 	nw = l*Dy(r);
857dd7cddfSDavid du Colombier 	md = malloc(sizeof(Memdata));
867dd7cddfSDavid du Colombier 	if(md == nil)
877dd7cddfSDavid du Colombier 		return nil;
887dd7cddfSDavid du Colombier 
897dd7cddfSDavid du Colombier 	md->ref = 1;
90*ec59a3ddSDavid du Colombier 	md->base = poolalloc(imagmem, sizeof(Memdata*)+(1+nw)*sizeof(ulong));
917dd7cddfSDavid du Colombier 	if(md->base == nil){
927dd7cddfSDavid du Colombier 		free(md);
937dd7cddfSDavid du Colombier 		return nil;
947dd7cddfSDavid du Colombier 	}
957dd7cddfSDavid du Colombier 
96*ec59a3ddSDavid du Colombier 	p = (uchar*)md->base;
97*ec59a3ddSDavid du Colombier 	*(Memdata**)p = md;
98*ec59a3ddSDavid du Colombier 	p += sizeof(Memdata*);
99*ec59a3ddSDavid du Colombier 
100*ec59a3ddSDavid du Colombier 	*(ulong*)p = getcallerpc(&r);
101*ec59a3ddSDavid du Colombier 	p += sizeof(ulong);
1027dd7cddfSDavid du Colombier 
1037dd7cddfSDavid du Colombier 	/* if this changes, memimagemove must change too */
104*ec59a3ddSDavid du Colombier 	md->bdata = p;
1057dd7cddfSDavid du Colombier 	md->allocd = 1;
1067dd7cddfSDavid du Colombier 
1077dd7cddfSDavid du Colombier 	i = allocmemimaged(r, chan, md, nil);
1087dd7cddfSDavid du Colombier 	if(i == nil){
1098ccd4a63SDavid du Colombier 		poolfree(imagmem, md->base);
1107dd7cddfSDavid du Colombier 		free(md);
1117dd7cddfSDavid du Colombier 		return nil;
1127dd7cddfSDavid du Colombier 	}
1137dd7cddfSDavid du Colombier 	md->imref = i;
1147dd7cddfSDavid du Colombier 	return i;
1157dd7cddfSDavid du Colombier }
1167dd7cddfSDavid du Colombier 
1177dd7cddfSDavid du Colombier void
_freememimage(Memimage * i)1187dd7cddfSDavid du Colombier _freememimage(Memimage *i)
1197dd7cddfSDavid du Colombier {
1207dd7cddfSDavid du Colombier 	if(i == nil)
1217dd7cddfSDavid du Colombier 		return;
1227dd7cddfSDavid du Colombier 	if(i->data->ref-- == 1 && i->data->allocd){
1237dd7cddfSDavid du Colombier 		if(i->data->base)
1248ccd4a63SDavid du Colombier 			poolfree(imagmem, i->data->base);
1257dd7cddfSDavid du Colombier 		free(i->data);
1267dd7cddfSDavid du Colombier 	}
1277dd7cddfSDavid du Colombier 	free(i);
1287dd7cddfSDavid du Colombier }
1297dd7cddfSDavid du Colombier 
1307dd7cddfSDavid du Colombier /*
1317dd7cddfSDavid du Colombier  * Wordaddr is deprecated.
1327dd7cddfSDavid du Colombier  */
1337dd7cddfSDavid du Colombier ulong*
wordaddr(Memimage * i,Point p)1347dd7cddfSDavid du Colombier wordaddr(Memimage *i, Point p)
1357dd7cddfSDavid du Colombier {
136*ec59a3ddSDavid du Colombier 	return (ulong*) ((uintptr)byteaddr(i, p) & ~(sizeof(ulong)-1));
1377dd7cddfSDavid du Colombier }
1387dd7cddfSDavid du Colombier 
1397dd7cddfSDavid du Colombier uchar*
byteaddr(Memimage * i,Point p)1407dd7cddfSDavid du Colombier byteaddr(Memimage *i, Point p)
1417dd7cddfSDavid du Colombier {
1427dd7cddfSDavid du Colombier 	uchar *a;
1437dd7cddfSDavid du Colombier 
1447dd7cddfSDavid du Colombier 	a = i->data->bdata+i->zero+sizeof(ulong)*p.y*i->width;
1457dd7cddfSDavid du Colombier 
1467dd7cddfSDavid du Colombier 	if(i->depth < 8){
1477dd7cddfSDavid du Colombier 		/*
1487dd7cddfSDavid du Colombier 		 * We need to always round down,
1497dd7cddfSDavid du Colombier 		 * but C rounds toward zero.
1507dd7cddfSDavid du Colombier 		 */
1517dd7cddfSDavid du Colombier 		int np;
1527dd7cddfSDavid du Colombier 		np = 8/i->depth;
1537dd7cddfSDavid du Colombier 		if(p.x < 0)
1547dd7cddfSDavid du Colombier 			return a+(p.x-np+1)/np;
1557dd7cddfSDavid du Colombier 		else
1567dd7cddfSDavid du Colombier 			return a+p.x/np;
1577dd7cddfSDavid du Colombier 	}
1587dd7cddfSDavid du Colombier 	else
1597dd7cddfSDavid du Colombier 		return a+p.x*(i->depth/8);
1607dd7cddfSDavid du Colombier }
1617dd7cddfSDavid du Colombier 
1627dd7cddfSDavid du Colombier int
memsetchan(Memimage * i,ulong chan)1637dd7cddfSDavid du Colombier memsetchan(Memimage *i, ulong chan)
1647dd7cddfSDavid du Colombier {
1657dd7cddfSDavid du Colombier 	int d;
1667dd7cddfSDavid du Colombier 	int t, j, k;
1677dd7cddfSDavid du Colombier 	ulong cc;
1687dd7cddfSDavid du Colombier 	int bytes;
1697dd7cddfSDavid du Colombier 
1707dd7cddfSDavid du Colombier 	if((d = chantodepth(chan)) == 0) {
1717dd7cddfSDavid du Colombier 		werrstr("bad channel descriptor");
1727dd7cddfSDavid du Colombier 		return -1;
1737dd7cddfSDavid du Colombier 	}
1747dd7cddfSDavid du Colombier 
1757dd7cddfSDavid du Colombier 	i->depth = d;
1767dd7cddfSDavid du Colombier 	i->chan = chan;
1777dd7cddfSDavid du Colombier 	i->flags &= ~(Fgrey|Falpha|Fcmap|Fbytes);
1787dd7cddfSDavid du Colombier 	bytes = 1;
1797dd7cddfSDavid du Colombier 	for(cc=chan, j=0, k=0; cc; j+=NBITS(cc), cc>>=8, k++){
1807dd7cddfSDavid du Colombier 		t=TYPE(cc);
1817dd7cddfSDavid du Colombier 		if(t < 0 || t >= NChan){
1827dd7cddfSDavid du Colombier 			werrstr("bad channel string");
1837dd7cddfSDavid du Colombier 			return -1;
1847dd7cddfSDavid du Colombier 		}
1857dd7cddfSDavid du Colombier 		if(t == CGrey)
1867dd7cddfSDavid du Colombier 			i->flags |= Fgrey;
1877dd7cddfSDavid du Colombier 		if(t == CAlpha)
1887dd7cddfSDavid du Colombier 			i->flags |= Falpha;
1897dd7cddfSDavid du Colombier 		if(t == CMap && i->cmap == nil){
1907dd7cddfSDavid du Colombier 			i->cmap = memdefcmap;
1917dd7cddfSDavid du Colombier 			i->flags |= Fcmap;
1927dd7cddfSDavid du Colombier 		}
1937dd7cddfSDavid du Colombier 
1947dd7cddfSDavid du Colombier 		i->shift[t] = j;
1957dd7cddfSDavid du Colombier 		i->mask[t] = (1<<NBITS(cc))-1;
1967dd7cddfSDavid du Colombier 		i->nbits[t] = NBITS(cc);
1977dd7cddfSDavid du Colombier 		if(NBITS(cc) != 8)
1987dd7cddfSDavid du Colombier 			bytes = 0;
1997dd7cddfSDavid du Colombier 	}
2007dd7cddfSDavid du Colombier 	i->nchan = k;
2017dd7cddfSDavid du Colombier 	if(bytes)
2027dd7cddfSDavid du Colombier 		i->flags |= Fbytes;
2037dd7cddfSDavid du Colombier 	return 0;
2047dd7cddfSDavid du Colombier }
205