xref: /plan9-contrib/sys/src/cmd/unix/drawterm/libmemdraw/alloc.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1*7dd7cddfSDavid du Colombier #include "../lib9.h"
2*7dd7cddfSDavid du Colombier 
3*7dd7cddfSDavid du Colombier #include "../libdraw/draw.h"
4*7dd7cddfSDavid du Colombier #include "../libmemdraw/memdraw.h"
5*7dd7cddfSDavid du Colombier 
6*7dd7cddfSDavid du Colombier void
7*7dd7cddfSDavid du Colombier memimagemove(void *from, void *to)
8*7dd7cddfSDavid du Colombier {
9*7dd7cddfSDavid du Colombier 	Memdata *md;
10*7dd7cddfSDavid du Colombier 
11*7dd7cddfSDavid du Colombier 	md = *(Memdata**)to;
12*7dd7cddfSDavid du Colombier 	if(md->base != from){
13*7dd7cddfSDavid du Colombier 		print("compacted data not right: #%p\n", md->base);
14*7dd7cddfSDavid du Colombier 		abort();
15*7dd7cddfSDavid du Colombier 	}
16*7dd7cddfSDavid du Colombier 	md->base = to;
17*7dd7cddfSDavid du Colombier 
18*7dd7cddfSDavid du Colombier 	/* if allocmemimage changes this must change too */
19*7dd7cddfSDavid du Colombier 	md->bdata = (uchar*)&md->base[2];
20*7dd7cddfSDavid du Colombier }
21*7dd7cddfSDavid du Colombier 
22*7dd7cddfSDavid du Colombier Memimage*
23*7dd7cddfSDavid du Colombier allocmemimaged(Rectangle r, ulong chan, Memdata *md, void *X)
24*7dd7cddfSDavid du Colombier {
25*7dd7cddfSDavid du Colombier 	int d;
26*7dd7cddfSDavid du Colombier 	ulong l;
27*7dd7cddfSDavid du Colombier 	Memimage *i;
28*7dd7cddfSDavid du Colombier 
29*7dd7cddfSDavid du Colombier 	if((d = chantodepth(chan)) == 0) {
30*7dd7cddfSDavid du Colombier 		werrstr("bad channel descriptor %.8lux", chan);
31*7dd7cddfSDavid du Colombier 		return nil;
32*7dd7cddfSDavid du Colombier 	}
33*7dd7cddfSDavid du Colombier 
34*7dd7cddfSDavid du Colombier 	l = wordsperline(r, d);
35*7dd7cddfSDavid du Colombier 
36*7dd7cddfSDavid du Colombier 	i = mallocz(sizeof(Memimage));
37*7dd7cddfSDavid du Colombier 	if(i == nil)
38*7dd7cddfSDavid du Colombier 		return nil;
39*7dd7cddfSDavid du Colombier 
40*7dd7cddfSDavid du Colombier 	i->data = md;
41*7dd7cddfSDavid du Colombier 	i->zero = sizeof(ulong)*l*r.min.y;
42*7dd7cddfSDavid du Colombier 
43*7dd7cddfSDavid du Colombier 	if(r.min.x >= 0)
44*7dd7cddfSDavid du Colombier 		i->zero += (r.min.x*d)/8;
45*7dd7cddfSDavid du Colombier 	else
46*7dd7cddfSDavid du Colombier 		i->zero -= (-r.min.x*d+7)/8;
47*7dd7cddfSDavid du Colombier 	i->zero = -i->zero;
48*7dd7cddfSDavid du Colombier 	i->width = l;
49*7dd7cddfSDavid du Colombier 	i->r = r;
50*7dd7cddfSDavid du Colombier 	i->clipr = r;
51*7dd7cddfSDavid du Colombier 	i->flags = 0;
52*7dd7cddfSDavid du Colombier 	i->layer = nil;
53*7dd7cddfSDavid du Colombier 	i->cmap = memdefcmap;
54*7dd7cddfSDavid du Colombier 	if(memsetchan(i, chan) < 0){
55*7dd7cddfSDavid du Colombier 		free(i);
56*7dd7cddfSDavid du Colombier 		return nil;
57*7dd7cddfSDavid du Colombier 	}
58*7dd7cddfSDavid du Colombier 	i->X = X;
59*7dd7cddfSDavid du Colombier 	return i;
60*7dd7cddfSDavid du Colombier }
61*7dd7cddfSDavid du Colombier 
62*7dd7cddfSDavid du Colombier Memimage*
63*7dd7cddfSDavid du Colombier _allocmemimage(Rectangle r, ulong chan)
64*7dd7cddfSDavid du Colombier {
65*7dd7cddfSDavid du Colombier 	int d;
66*7dd7cddfSDavid du Colombier 	ulong l, nw;
67*7dd7cddfSDavid du Colombier 	Memdata *md;
68*7dd7cddfSDavid du Colombier 	Memimage *i;
69*7dd7cddfSDavid du Colombier 
70*7dd7cddfSDavid du Colombier 	if((d = chantodepth(chan)) == 0) {
71*7dd7cddfSDavid du Colombier 		werrstr("bad channel descriptor %.8lux", chan);
72*7dd7cddfSDavid du Colombier 		return nil;
73*7dd7cddfSDavid du Colombier 	}
74*7dd7cddfSDavid du Colombier 
75*7dd7cddfSDavid du Colombier 	l = wordsperline(r, d);
76*7dd7cddfSDavid du Colombier 	nw = l*Dy(r);
77*7dd7cddfSDavid du Colombier 	md = malloc(sizeof(Memdata));
78*7dd7cddfSDavid du Colombier 	if(md == nil)
79*7dd7cddfSDavid du Colombier 		return nil;
80*7dd7cddfSDavid du Colombier 
81*7dd7cddfSDavid du Colombier 	md->ref = 1;
82*7dd7cddfSDavid du Colombier 	md->base = mallocz((2+nw)*sizeof(ulong));
83*7dd7cddfSDavid du Colombier 	if(md->base == nil){
84*7dd7cddfSDavid du Colombier 		free(md);
85*7dd7cddfSDavid du Colombier 		return nil;
86*7dd7cddfSDavid du Colombier 	}
87*7dd7cddfSDavid du Colombier 
88*7dd7cddfSDavid du Colombier 	md->base[0] = (ulong)md;
89*7dd7cddfSDavid du Colombier 	md->base[1] = getcallerpc(&r);
90*7dd7cddfSDavid du Colombier 
91*7dd7cddfSDavid du Colombier 	/* if this changes, memimagemove must change too */
92*7dd7cddfSDavid du Colombier 	md->bdata = (uchar*)&md->base[2];
93*7dd7cddfSDavid du Colombier 
94*7dd7cddfSDavid du Colombier 	md->allocd = 1;
95*7dd7cddfSDavid du Colombier 
96*7dd7cddfSDavid du Colombier 	i = allocmemimaged(r, chan, md, nil);
97*7dd7cddfSDavid du Colombier 	if(i == nil){
98*7dd7cddfSDavid du Colombier 		free(md);
99*7dd7cddfSDavid du Colombier 		return nil;
100*7dd7cddfSDavid du Colombier 	}
101*7dd7cddfSDavid du Colombier 	md->imref = i;
102*7dd7cddfSDavid du Colombier 	return i;
103*7dd7cddfSDavid du Colombier }
104*7dd7cddfSDavid du Colombier 
105*7dd7cddfSDavid du Colombier void
106*7dd7cddfSDavid du Colombier _freememimage(Memimage *i)
107*7dd7cddfSDavid du Colombier {
108*7dd7cddfSDavid du Colombier 	if(i == nil)
109*7dd7cddfSDavid du Colombier 		return;
110*7dd7cddfSDavid du Colombier 	if(i->data->ref-- == 1 && i->data->allocd){
111*7dd7cddfSDavid du Colombier 		if(i->data->base)
112*7dd7cddfSDavid du Colombier 			free(i->data->base);
113*7dd7cddfSDavid du Colombier 		free(i->data);
114*7dd7cddfSDavid du Colombier 	}
115*7dd7cddfSDavid du Colombier 	free(i);
116*7dd7cddfSDavid du Colombier }
117*7dd7cddfSDavid du Colombier 
118*7dd7cddfSDavid du Colombier /*
119*7dd7cddfSDavid du Colombier  * Wordaddr is deprecated.
120*7dd7cddfSDavid du Colombier  */
121*7dd7cddfSDavid du Colombier ulong*
122*7dd7cddfSDavid du Colombier wordaddr(Memimage *i, Point p)
123*7dd7cddfSDavid du Colombier {
124*7dd7cddfSDavid du Colombier 	return (ulong*) ((ulong)byteaddr(i, p) & ~(sizeof(ulong)-1));
125*7dd7cddfSDavid du Colombier }
126*7dd7cddfSDavid du Colombier 
127*7dd7cddfSDavid du Colombier uchar*
128*7dd7cddfSDavid du Colombier byteaddr(Memimage *i, Point p)
129*7dd7cddfSDavid du Colombier {
130*7dd7cddfSDavid du Colombier 	uchar *a;
131*7dd7cddfSDavid du Colombier 
132*7dd7cddfSDavid du Colombier 	a = i->data->bdata+i->zero+sizeof(ulong)*p.y*i->width;
133*7dd7cddfSDavid du Colombier 
134*7dd7cddfSDavid du Colombier 	if(i->depth < 8){
135*7dd7cddfSDavid du Colombier 		/*
136*7dd7cddfSDavid du Colombier 		 * We need to always round down,
137*7dd7cddfSDavid du Colombier 		 * but C rounds toward zero.
138*7dd7cddfSDavid du Colombier 		 */
139*7dd7cddfSDavid du Colombier 		int np;
140*7dd7cddfSDavid du Colombier 		np = 8/i->depth;
141*7dd7cddfSDavid du Colombier 		if(p.x < 0)
142*7dd7cddfSDavid du Colombier 			return a+(p.x-np+1)/np;
143*7dd7cddfSDavid du Colombier 		else
144*7dd7cddfSDavid du Colombier 			return a+p.x/np;
145*7dd7cddfSDavid du Colombier 	}
146*7dd7cddfSDavid du Colombier 	else
147*7dd7cddfSDavid du Colombier 		return a+p.x*(i->depth/8);
148*7dd7cddfSDavid du Colombier }
149*7dd7cddfSDavid du Colombier 
150*7dd7cddfSDavid du Colombier void
151*7dd7cddfSDavid du Colombier _memfillcolor(Memimage *i, ulong val)
152*7dd7cddfSDavid du Colombier {
153*7dd7cddfSDavid du Colombier 	static Memimage *paint;
154*7dd7cddfSDavid du Colombier 	uchar *data;
155*7dd7cddfSDavid du Colombier 
156*7dd7cddfSDavid du Colombier 	if(paint == nil){
157*7dd7cddfSDavid du Colombier 		paint = allocmemimage(Rect(0,0,1,1), ARGB32);
158*7dd7cddfSDavid du Colombier 		if(paint == nil)
159*7dd7cddfSDavid du Colombier 			return;
160*7dd7cddfSDavid du Colombier 		paint->clipr = Rect(-0x3FFFFFF,-0x3FFFFFF,0x3FFFFFF,0x3FFFFFF);
161*7dd7cddfSDavid du Colombier 		paint->flags |= Frepl;
162*7dd7cddfSDavid du Colombier 	}
163*7dd7cddfSDavid du Colombier 
164*7dd7cddfSDavid du Colombier 	data = byteaddr(paint, Pt(0,0));
165*7dd7cddfSDavid du Colombier 	data[0] = val>>8;	/* blue */
166*7dd7cddfSDavid du Colombier 	data[1] = val>>16;	/* green */
167*7dd7cddfSDavid du Colombier 	data[2] = val>>24;	/* red */
168*7dd7cddfSDavid du Colombier 	data[3] = val;		/* alpha */
169*7dd7cddfSDavid du Colombier 
170*7dd7cddfSDavid du Colombier 	memimagedraw(i, i->r, paint, ZP, nil, ZP);
171*7dd7cddfSDavid du Colombier }
172*7dd7cddfSDavid du Colombier 
173*7dd7cddfSDavid du Colombier int
174*7dd7cddfSDavid du Colombier memsetchan(Memimage *i, ulong chan)
175*7dd7cddfSDavid du Colombier {
176*7dd7cddfSDavid du Colombier 	int d;
177*7dd7cddfSDavid du Colombier 	int t, j, k;
178*7dd7cddfSDavid du Colombier 	ulong cc;
179*7dd7cddfSDavid du Colombier 	int bytes;
180*7dd7cddfSDavid du Colombier 
181*7dd7cddfSDavid du Colombier 	assert(i->X == nil);
182*7dd7cddfSDavid du Colombier 	if((d = chantodepth(chan)) == 0) {
183*7dd7cddfSDavid du Colombier 		werrstr("bad channel descriptor");
184*7dd7cddfSDavid du Colombier 		return -1;
185*7dd7cddfSDavid du Colombier 	}
186*7dd7cddfSDavid du Colombier 
187*7dd7cddfSDavid du Colombier 	i->depth = d;
188*7dd7cddfSDavid du Colombier 	i->chan = chan;
189*7dd7cddfSDavid du Colombier 	i->flags &= ~(Fgrey|Falpha|Fcmap|Fbytes);
190*7dd7cddfSDavid du Colombier 	bytes = 1;
191*7dd7cddfSDavid du Colombier 	for(cc=chan, j=0, k=0; cc; j+=NBITS(cc), cc>>=8, k++){
192*7dd7cddfSDavid du Colombier 		t=TYPE(cc);
193*7dd7cddfSDavid du Colombier 		if(t < 0 || t >= NChan){
194*7dd7cddfSDavid du Colombier 			werrstr("bad channel string");
195*7dd7cddfSDavid du Colombier 			return -1;
196*7dd7cddfSDavid du Colombier 		}
197*7dd7cddfSDavid du Colombier 		if(t == CGrey)
198*7dd7cddfSDavid du Colombier 			i->flags |= Fgrey;
199*7dd7cddfSDavid du Colombier 		if(t == CAlpha)
200*7dd7cddfSDavid du Colombier 			i->flags |= Falpha;
201*7dd7cddfSDavid du Colombier 		if(t == CMap && i->cmap == nil){
202*7dd7cddfSDavid du Colombier 			i->cmap = memdefcmap;
203*7dd7cddfSDavid du Colombier 			i->flags |= Fcmap;
204*7dd7cddfSDavid du Colombier 		}
205*7dd7cddfSDavid du Colombier 
206*7dd7cddfSDavid du Colombier 		i->shift[t] = j;
207*7dd7cddfSDavid du Colombier 		i->mask[t] = (1<<NBITS(cc))-1;
208*7dd7cddfSDavid du Colombier 		i->nbits[t] = NBITS(cc);
209*7dd7cddfSDavid du Colombier 		if(NBITS(cc) != 8)
210*7dd7cddfSDavid du Colombier 			bytes = 0;
211*7dd7cddfSDavid du Colombier 	}
212*7dd7cddfSDavid du Colombier 	i->nchan = k;
213*7dd7cddfSDavid du Colombier 	if(bytes)
214*7dd7cddfSDavid du Colombier 		i->flags |= Fbytes;
215*7dd7cddfSDavid du Colombier 	return 0;
216*7dd7cddfSDavid du Colombier }
217