xref: /plan9-contrib/sys/src/libmemdraw/alloc.c (revision 6f1f24dd981116678e9fd1c5fb4c6ae548570725)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <memdraw.h>
57dd7cddfSDavid du Colombier #include <pool.h>
67dd7cddfSDavid du Colombier 
7*6f1f24ddSDavid du Colombier extern Pool* imagmem;
8*6f1f24ddSDavid du Colombier 
9*6f1f24ddSDavid du Colombier void
memdrawallocinit(void)10*6f1f24ddSDavid du Colombier memdrawallocinit(void)
11*6f1f24ddSDavid du Colombier {
12*6f1f24ddSDavid du Colombier 	if(strcmp(imagmem->name, "Image") == 0 || strcmp(imagmem->name, "image") == 0)
13*6f1f24ddSDavid du Colombier 		imagmem->move = memimagemove;
14*6f1f24ddSDavid du Colombier }
15*6f1f24ddSDavid du Colombier 
167dd7cddfSDavid du Colombier void
memimagemove(void * from,void * to)177dd7cddfSDavid du Colombier memimagemove(void *from, void *to)
187dd7cddfSDavid du Colombier {
197dd7cddfSDavid du Colombier 	Memdata *md;
207dd7cddfSDavid du Colombier 
217dd7cddfSDavid du Colombier 	md = *(Memdata**)to;
227dd7cddfSDavid du Colombier 	if(md->base != from){
237dd7cddfSDavid du Colombier 		print("compacted data not right: #%p\n", md->base);
247dd7cddfSDavid du Colombier 		abort();
257dd7cddfSDavid du Colombier 	}
267dd7cddfSDavid du Colombier 	md->base = to;
277dd7cddfSDavid du Colombier 
287dd7cddfSDavid du Colombier 	/* if allocmemimage changes this must change too */
2990e65e0fSDavid du Colombier 	md->bdata = (uchar*)md->base+sizeof(Memdata*)+sizeof(ulong);
307dd7cddfSDavid du Colombier }
317dd7cddfSDavid du Colombier 
327dd7cddfSDavid du Colombier Memimage*
allocmemimaged(Rectangle r,ulong chan,Memdata * md)337dd7cddfSDavid du Colombier allocmemimaged(Rectangle r, ulong chan, Memdata *md)
347dd7cddfSDavid du Colombier {
357dd7cddfSDavid du Colombier 	int d;
367dd7cddfSDavid du Colombier 	ulong l;
377dd7cddfSDavid du Colombier 	Memimage *i;
387dd7cddfSDavid du Colombier 
39d3c05884SDavid du Colombier 	if(Dx(r) <= 0 || Dy(r) <= 0){
40d3c05884SDavid du Colombier 		werrstr("bad rectangle %R", r);
41d3c05884SDavid du Colombier 		return nil;
42d3c05884SDavid du Colombier 	}
437dd7cddfSDavid du Colombier 	if((d = chantodepth(chan)) == 0) {
447dd7cddfSDavid du Colombier 		werrstr("bad channel descriptor %.8lux", chan);
457dd7cddfSDavid du Colombier 		return nil;
467dd7cddfSDavid du Colombier 	}
477dd7cddfSDavid du Colombier 
487dd7cddfSDavid du Colombier 	l = wordsperline(r, d);
497dd7cddfSDavid du Colombier 
507dd7cddfSDavid du Colombier 	i = mallocz(sizeof(Memimage), 1);
517dd7cddfSDavid du Colombier 	if(i == nil)
527dd7cddfSDavid du Colombier 		return nil;
537dd7cddfSDavid du Colombier 
547dd7cddfSDavid du Colombier 	i->data = md;
557dd7cddfSDavid du Colombier 	i->zero = sizeof(ulong)*l*r.min.y;
567dd7cddfSDavid du Colombier 
577dd7cddfSDavid du Colombier 	if(r.min.x >= 0)
587dd7cddfSDavid du Colombier 		i->zero += (r.min.x*d)/8;
597dd7cddfSDavid du Colombier 	else
607dd7cddfSDavid du Colombier 		i->zero -= (-r.min.x*d+7)/8;
617dd7cddfSDavid du Colombier 	i->zero = -i->zero;
627dd7cddfSDavid du Colombier 	i->width = l;
637dd7cddfSDavid du Colombier 	i->r = r;
647dd7cddfSDavid du Colombier 	i->clipr = r;
657dd7cddfSDavid du Colombier 	i->flags = 0;
667dd7cddfSDavid du Colombier 	i->layer = nil;
677dd7cddfSDavid du Colombier 	i->cmap = memdefcmap;
687dd7cddfSDavid du Colombier 	if(memsetchan(i, chan) < 0){
697dd7cddfSDavid du Colombier 		free(i);
707dd7cddfSDavid du Colombier 		return nil;
717dd7cddfSDavid du Colombier 	}
727dd7cddfSDavid du Colombier 	return i;
737dd7cddfSDavid du Colombier }
747dd7cddfSDavid du Colombier 
757dd7cddfSDavid du Colombier Memimage*
allocmemimage(Rectangle r,ulong chan)767dd7cddfSDavid du Colombier allocmemimage(Rectangle r, ulong chan)
777dd7cddfSDavid du Colombier {
787dd7cddfSDavid du Colombier 	int d;
7990e65e0fSDavid du Colombier 	uchar *p;
807dd7cddfSDavid du Colombier 	ulong l, nw;
817dd7cddfSDavid du Colombier 	Memdata *md;
827dd7cddfSDavid du Colombier 	Memimage *i;
837dd7cddfSDavid du Colombier 
847dd7cddfSDavid du Colombier 	if((d = chantodepth(chan)) == 0) {
857dd7cddfSDavid du Colombier 		werrstr("bad channel descriptor %.8lux", chan);
867dd7cddfSDavid du Colombier 		return nil;
877dd7cddfSDavid du Colombier 	}
887dd7cddfSDavid du Colombier 
897dd7cddfSDavid du Colombier 	l = wordsperline(r, d);
907dd7cddfSDavid du Colombier 	nw = l*Dy(r);
917dd7cddfSDavid du Colombier 	md = malloc(sizeof(Memdata));
927dd7cddfSDavid du Colombier 	if(md == nil)
937dd7cddfSDavid du Colombier 		return nil;
947dd7cddfSDavid du Colombier 
957dd7cddfSDavid du Colombier 	md->ref = 1;
9690e65e0fSDavid du Colombier 	md->base = poolalloc(imagmem, sizeof(Memdata*)+(1+nw)*sizeof(ulong));
977dd7cddfSDavid du Colombier 	if(md->base == nil){
987dd7cddfSDavid du Colombier 		free(md);
997dd7cddfSDavid du Colombier 		return nil;
1007dd7cddfSDavid du Colombier 	}
1017dd7cddfSDavid du Colombier 
10290e65e0fSDavid du Colombier 	p = (uchar*)md->base;
10390e65e0fSDavid du Colombier 	*(Memdata**)p = md;
10490e65e0fSDavid du Colombier 	p += sizeof(Memdata*);
10590e65e0fSDavid du Colombier 
10690e65e0fSDavid du Colombier 	*(ulong*)p = getcallerpc(&r);
10790e65e0fSDavid du Colombier 	p += sizeof(ulong);
1087dd7cddfSDavid du Colombier 
1097dd7cddfSDavid du Colombier 	/* if this changes, memimagemove must change too */
11090e65e0fSDavid du Colombier 	md->bdata = p;
1117dd7cddfSDavid du Colombier 	md->allocd = 1;
1127dd7cddfSDavid du Colombier 
1137dd7cddfSDavid du Colombier 	i = allocmemimaged(r, chan, md);
1147dd7cddfSDavid du Colombier 	if(i == nil){
1156a9fc400SDavid du Colombier 		poolfree(imagmem, md->base);
1167dd7cddfSDavid du Colombier 		free(md);
1177dd7cddfSDavid du Colombier 		return nil;
1187dd7cddfSDavid du Colombier 	}
1197dd7cddfSDavid du Colombier 	md->imref = i;
1207dd7cddfSDavid du Colombier 	return i;
1217dd7cddfSDavid du Colombier }
1227dd7cddfSDavid du Colombier 
1237dd7cddfSDavid du Colombier void
freememimage(Memimage * i)1247dd7cddfSDavid du Colombier freememimage(Memimage *i)
1257dd7cddfSDavid du Colombier {
1267dd7cddfSDavid du Colombier 	if(i == nil)
1277dd7cddfSDavid du Colombier 		return;
1287dd7cddfSDavid du Colombier 	if(i->data->ref-- == 1 && i->data->allocd){
1297dd7cddfSDavid du Colombier 		if(i->data->base)
1307dd7cddfSDavid du Colombier 			poolfree(imagmem, i->data->base);
1317dd7cddfSDavid du Colombier 		free(i->data);
1327dd7cddfSDavid du Colombier 	}
1337dd7cddfSDavid du Colombier 	free(i);
1347dd7cddfSDavid du Colombier }
135