xref: /plan9-contrib/sys/src/libmemdraw/alloc.c (revision 6f1f24dd981116678e9fd1c5fb4c6ae548570725)
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <memdraw.h>
5 #include <pool.h>
6 
7 extern Pool* imagmem;
8 
9 void
memdrawallocinit(void)10 memdrawallocinit(void)
11 {
12 	if(strcmp(imagmem->name, "Image") == 0 || strcmp(imagmem->name, "image") == 0)
13 		imagmem->move = memimagemove;
14 }
15 
16 void
memimagemove(void * from,void * to)17 memimagemove(void *from, void *to)
18 {
19 	Memdata *md;
20 
21 	md = *(Memdata**)to;
22 	if(md->base != from){
23 		print("compacted data not right: #%p\n", md->base);
24 		abort();
25 	}
26 	md->base = to;
27 
28 	/* if allocmemimage changes this must change too */
29 	md->bdata = (uchar*)md->base+sizeof(Memdata*)+sizeof(ulong);
30 }
31 
32 Memimage*
allocmemimaged(Rectangle r,ulong chan,Memdata * md)33 allocmemimaged(Rectangle r, ulong chan, Memdata *md)
34 {
35 	int d;
36 	ulong l;
37 	Memimage *i;
38 
39 	if(Dx(r) <= 0 || Dy(r) <= 0){
40 		werrstr("bad rectangle %R", r);
41 		return nil;
42 	}
43 	if((d = chantodepth(chan)) == 0) {
44 		werrstr("bad channel descriptor %.8lux", chan);
45 		return nil;
46 	}
47 
48 	l = wordsperline(r, d);
49 
50 	i = mallocz(sizeof(Memimage), 1);
51 	if(i == nil)
52 		return nil;
53 
54 	i->data = md;
55 	i->zero = sizeof(ulong)*l*r.min.y;
56 
57 	if(r.min.x >= 0)
58 		i->zero += (r.min.x*d)/8;
59 	else
60 		i->zero -= (-r.min.x*d+7)/8;
61 	i->zero = -i->zero;
62 	i->width = l;
63 	i->r = r;
64 	i->clipr = r;
65 	i->flags = 0;
66 	i->layer = nil;
67 	i->cmap = memdefcmap;
68 	if(memsetchan(i, chan) < 0){
69 		free(i);
70 		return nil;
71 	}
72 	return i;
73 }
74 
75 Memimage*
allocmemimage(Rectangle r,ulong chan)76 allocmemimage(Rectangle r, ulong chan)
77 {
78 	int d;
79 	uchar *p;
80 	ulong l, nw;
81 	Memdata *md;
82 	Memimage *i;
83 
84 	if((d = chantodepth(chan)) == 0) {
85 		werrstr("bad channel descriptor %.8lux", chan);
86 		return nil;
87 	}
88 
89 	l = wordsperline(r, d);
90 	nw = l*Dy(r);
91 	md = malloc(sizeof(Memdata));
92 	if(md == nil)
93 		return nil;
94 
95 	md->ref = 1;
96 	md->base = poolalloc(imagmem, sizeof(Memdata*)+(1+nw)*sizeof(ulong));
97 	if(md->base == nil){
98 		free(md);
99 		return nil;
100 	}
101 
102 	p = (uchar*)md->base;
103 	*(Memdata**)p = md;
104 	p += sizeof(Memdata*);
105 
106 	*(ulong*)p = getcallerpc(&r);
107 	p += sizeof(ulong);
108 
109 	/* if this changes, memimagemove must change too */
110 	md->bdata = p;
111 	md->allocd = 1;
112 
113 	i = allocmemimaged(r, chan, md);
114 	if(i == nil){
115 		poolfree(imagmem, md->base);
116 		free(md);
117 		return nil;
118 	}
119 	md->imref = i;
120 	return i;
121 }
122 
123 void
freememimage(Memimage * i)124 freememimage(Memimage *i)
125 {
126 	if(i == nil)
127 		return;
128 	if(i->data->ref-- == 1 && i->data->allocd){
129 		if(i->data->base)
130 			poolfree(imagmem, i->data->base);
131 		free(i->data);
132 	}
133 	free(i);
134 }
135