Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <memdraw.h>
6 #define poolalloc(a, b) malloc(b)
7 #define poolfree(a, b) free(b)
9 void
10 memimagemove(void *from, void *to)
11 {
12 Memdata *md;
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;
21 /* if allocmemimage changes this must change too */
22 md->bdata = (uchar*)md->base+sizeof(Memdata*)+sizeof(ulong);
23 }
25 Memimage*
26 allocmemimaged(Rectangle r, u32int chan, Memdata *md, void *X)
27 {
28 int d;
29 u32int l;
30 Memimage *i;
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 }
41 l = wordsperline(r, d);
43 i = mallocz(sizeof(Memimage), 1);
44 if(i == nil)
45 return nil;
47 i->X = X;
48 i->data = md;
49 i->zero = sizeof(u32int)*l*r.min.y;
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 }
69 Memimage*
70 _allocmemimage(Rectangle r, u32int chan)
71 {
72 int d;
73 u32int l, nw;
74 uchar *p;
75 Memdata *md;
76 Memimage *i;
78 if((d = chantodepth(chan)) == 0) {
79 werrstr("bad channel descriptor %.8lux", chan);
80 return nil;
81 }
83 l = wordsperline(r, d);
84 nw = l*Dy(r);
85 md = malloc(sizeof(Memdata));
86 if(md == nil)
87 return nil;
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 }
96 p = (uchar*)md->base;
97 *(Memdata**)p = md;
98 p += sizeof(Memdata*);
100 *(ulong*)p = getcallerpc(&r);
101 p += sizeof(ulong);
103 /* if this changes, memimagemove must change too */
104 md->bdata = p;
105 md->allocd = 1;
107 i = allocmemimaged(r, chan, md, nil);
108 if(i == nil){
109 poolfree(imagmem, md->base);
110 free(md);
111 return nil;
113 md->imref = i;
114 return i;
117 void
118 _freememimage(Memimage *i)
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);
127 free(i);
130 /*
131 * Wordaddr is deprecated.
132 */
133 u32int*
134 wordaddr(Memimage *i, Point p)
136 return (u32int*) ((ulong)byteaddr(i, p) & ~(sizeof(u32int)-1));
139 uchar*
140 byteaddr(Memimage *i, Point p)
142 uchar *a;
144 /* careful to sign-extend negative p.y for 64-bits */
145 a = i->data->bdata+i->zero+(int)(sizeof(u32int)*p.y*i->width);
147 if(i->depth < 8){
148 /*
149 * We need to always round down,
150 * but C rounds toward zero.
151 */
152 int np;
153 np = 8/i->depth;
154 if(p.x < 0)
155 return a+(p.x-np+1)/np;
156 else
157 return a+p.x/np;
159 else
160 return a+p.x*(i->depth/8);
163 int
164 memsetchan(Memimage *i, u32int chan)
166 int d;
167 int t, j, k;
168 u32int cc;
169 int bytes;
171 if((d = chantodepth(chan)) == 0) {
172 werrstr("bad channel descriptor");
173 return -1;
176 i->depth = d;
177 i->chan = chan;
178 i->flags &= ~(Fgrey|Falpha|Fcmap|Fbytes);
179 bytes = 1;
180 for(cc=chan, j=0, k=0; cc; j+=NBITS(cc), cc>>=8, k++){
181 t=TYPE(cc);
182 if(t < 0 || t >= NChan){
183 werrstr("bad channel string");
184 return -1;
186 if(t == CGrey)
187 i->flags |= Fgrey;
188 if(t == CAlpha)
189 i->flags |= Falpha;
190 if(t == CMap && i->cmap == nil){
191 i->cmap = memdefcmap;
192 i->flags |= Fcmap;
195 i->shift[t] = j;
196 i->mask[t] = (1<<NBITS(cc))-1;
197 i->nbits[t] = NBITS(cc);
198 if(NBITS(cc) != 8)
199 bytes = 0;
201 i->nchan = k;
202 if(bytes)
203 i->flags |= Fbytes;
204 return 0;