xref: /plan9/sys/src/cmd/unix/drawterm/libmemdraw/alloc.c (revision ec59a3ddbfceee0efe34584c2c9981a5e5ff1ec4)
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
memimagemove(void * from,void * to)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*
allocmemimaged(Rectangle r,ulong chan,Memdata * md,void * X)26 allocmemimaged(Rectangle r, ulong chan, Memdata *md, void *X)
27 {
28 	int d;
29 	ulong 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(ulong)*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*
_allocmemimage(Rectangle r,ulong chan)70 _allocmemimage(Rectangle r, ulong 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
_freememimage(Memimage * i)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 ulong*
wordaddr(Memimage * i,Point p)134 wordaddr(Memimage *i, Point p)
135 {
136 	return (ulong*) ((uintptr)byteaddr(i, p) & ~(sizeof(ulong)-1));
137 }
138 
139 uchar*
byteaddr(Memimage * i,Point p)140 byteaddr(Memimage *i, Point p)
141 {
142 	uchar *a;
143 
144 	a = i->data->bdata+i->zero+sizeof(ulong)*p.y*i->width;
145 
146 	if(i->depth < 8){
147 		/*
148 		 * We need to always round down,
149 		 * but C rounds toward zero.
150 		 */
151 		int np;
152 		np = 8/i->depth;
153 		if(p.x < 0)
154 			return a+(p.x-np+1)/np;
155 		else
156 			return a+p.x/np;
157 	}
158 	else
159 		return a+p.x*(i->depth/8);
160 }
161 
162 int
memsetchan(Memimage * i,ulong chan)163 memsetchan(Memimage *i, ulong chan)
164 {
165 	int d;
166 	int t, j, k;
167 	ulong cc;
168 	int bytes;
169 
170 	if((d = chantodepth(chan)) == 0) {
171 		werrstr("bad channel descriptor");
172 		return -1;
173 	}
174 
175 	i->depth = d;
176 	i->chan = chan;
177 	i->flags &= ~(Fgrey|Falpha|Fcmap|Fbytes);
178 	bytes = 1;
179 	for(cc=chan, j=0, k=0; cc; j+=NBITS(cc), cc>>=8, k++){
180 		t=TYPE(cc);
181 		if(t < 0 || t >= NChan){
182 			werrstr("bad channel string");
183 			return -1;
184 		}
185 		if(t == CGrey)
186 			i->flags |= Fgrey;
187 		if(t == CAlpha)
188 			i->flags |= Falpha;
189 		if(t == CMap && i->cmap == nil){
190 			i->cmap = memdefcmap;
191 			i->flags |= Fcmap;
192 		}
193 
194 		i->shift[t] = j;
195 		i->mask[t] = (1<<NBITS(cc))-1;
196 		i->nbits[t] = NBITS(cc);
197 		if(NBITS(cc) != 8)
198 			bytes = 0;
199 	}
200 	i->nchan = k;
201 	if(bytes)
202 		i->flags |= Fbytes;
203 	return 0;
204 }
205