153 lines · 2.4 KB · C
RawDownload
/* very primative draw allocator with no compaction */#include <u.h>#include <libc.h>#include <draw.h>#include <memdraw.h> #define	compactmalloc(x)		malloc(x)#define	compactfree(pool, x)	free(x)#define Overhead	(sizeof(Memdata*)+sizeof(uintptr)) /* conflict for %P and %R; this is a gross fix. */#ifdef notdefintPfmt(Fmt *f){	extern int fmtP(Fmt*); 	return fmtP(f);} intRfmt(Fmt *f){	extern int fmtR(Fmt*); 	return fmtR(f);}#endif voidmemdrawallocinit(void){} static void·memimagemove(void *from, void *to){	Memdata *md; 	md = *(Memdata**)to;	if(md->base != from){		print("compacted data not right: #%p\n", md->base);		abort();	}	md->base = to; 	/* if allocmemimage changes this must change too */	md->bdata = (uchar*)md->base+Overhead;} Memimage*allocmemimaged(Rectangle r, ulong chan, Memdata *md){	int d;	ulong l;	Memimage *i; 	if(Dx(r) <= 0 || Dy(r) <= 0){		werrstr("bad rectangle %R", r);		return nil;	}	if((d = chantodepth(chan)) == 0) {		werrstr("bad channel descriptor %.8lux", chan);		return nil;	} 	l = wordsperline(r, d); 	i = mallocz(sizeof(Memimage), 1);	if(i == nil)		return nil; 	i->data = md;	i->zero = sizeof(ulong)*l*r.min.y;		if(r.min.x >= 0)		i->zero += (r.min.x*d)/8;	else		i->zero -= (-r.min.x*d+7)/8;	i->zero = -i->zero;	i->width = l;	i->r = r;	i->clipr = r;	i->flags = 0;	i->layer = nil;	i->cmap = memdefcmap;	if(memsetchan(i, chan) < 0){		free(i);		return nil;	}	return i;} Memimage*allocmemimage(Rectangle r, ulong chan){	int d;	uchar *p;	ulong l, nw;	Memdata *md;	Memimage *i; 	if((d = chantodepth(chan)) == 0) {		werrstr("bad channel descriptor %.8lux", chan);		return nil;	} 	l = wordsperline(r, d);	nw = l*Dy(r);	md = malloc(sizeof(Memdata));	if(md == nil)		return nil; 	md->ref = 1;	md->base = compactmalloc(Overhead+nw*sizeof(ulong));	if(md->base == nil){		free(md);		return nil;	} 	p = (uchar*)md->base;	*(Memdata**)p = md;	p += sizeof(Memdata*); 	*(uintptr*)p = getcallerpc(&r);	p += sizeof(uintptr); 	/* if this changes, memimagemove must change too */	md->bdata = p;	md->allocd = 1; 	i = allocmemimaged(r, chan, md);	if(i == nil){		compactfree(imagmem, md->base);		free(md);		return nil;	}	md->imref = i;	return i;} voidfreememimage(Memimage *i){	if(i == nil)		return;	if(i->data->ref-- == 1 && i->data->allocd){		if(i->data->base)			compactfree(imagmem, i->data->base);		free(i->data);	}	free(i);}