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