]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libmemdraw/alloc.c
wifi: learn target ip address from neighbor advertisements in dmat proxy
[plan9front.git] / sys / src / libmemdraw / alloc.c
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <memdraw.h>
5 #include <pool.h>
6
7 void
8 memimagemove(void *from, void *to)
9 {
10         Memdata *md;
11
12         md = *(Memdata**)to;
13         if(md->base != from){
14                 print("compacted data not right: #%p\n", md->base);
15                 abort();
16         }
17         md->base = to;
18
19         /* if allocmemimage changes this must change too */
20         md->bdata = (uchar*)md->base+sizeof(Memdata*)+sizeof(ulong);
21 }
22
23 Memimage*
24 allocmemimaged(Rectangle r, ulong chan, Memdata *md)
25 {
26         int d;
27         ulong l;
28         Memimage *i;
29
30         if((d = chantodepth(chan)) == 0) {
31                 werrstr("bad channel descriptor %.8lux", chan);
32                 return nil;
33         }
34         if(badrect(r)){
35                 werrstr("bad rectangle %R", r);
36                 return nil;
37         }
38
39         l = wordsperline(r, d);
40
41         i = mallocz(sizeof(Memimage), 1);
42         if(i == nil)
43                 return nil;
44
45         i->data = md;
46         i->zero = sizeof(ulong)*l*r.min.y;
47         
48         if(r.min.x >= 0)
49                 i->zero += (r.min.x*d)/8;
50         else
51                 i->zero -= (-r.min.x*d+7)/8;
52         i->zero = -i->zero;
53         i->width = l;
54         i->r = r;
55         i->clipr = r;
56         i->flags = 0;
57         i->layer = nil;
58         i->cmap = memdefcmap;
59         if(memsetchan(i, chan) < 0){
60                 free(i);
61                 return nil;
62         }
63         return i;
64 }
65
66 Memimage*
67 allocmemimage(Rectangle r, ulong chan)
68 {
69         int d;
70         uchar *p;
71         ulong l, nw;
72         Memdata *md;
73         Memimage *i;
74
75         if((d = chantodepth(chan)) == 0) {
76                 werrstr("bad channel descriptor %.8lux", chan);
77                 return nil;
78         }
79         if(badrect(r)){
80                 werrstr("bad rectangle %R", r);
81                 return nil;
82         }
83
84         l = wordsperline(r, d);
85
86         nw = l*Dy(r);
87         md = malloc(sizeof(Memdata));
88         if(md == nil)
89                 return nil;
90
91         md->ref = 1;
92         md->base = poolalloc(imagmem, sizeof(Memdata*)+(1+nw)*sizeof(ulong));
93         if(md->base == nil){
94                 free(md);
95                 return nil;
96         }
97
98         p = (uchar*)md->base;
99         *(Memdata**)p = md;
100         p += sizeof(Memdata*);
101
102         *(ulong*)p = getcallerpc(&r);
103         p += sizeof(ulong);
104
105         /* if this changes, memimagemove must change too */
106         md->bdata = p;
107         md->allocd = 1;
108
109         i = allocmemimaged(r, chan, md);
110         if(i == nil){
111                 poolfree(imagmem, md->base);
112                 free(md);
113                 return nil;
114         }
115         md->imref = i;
116         return i;
117 }
118
119 void
120 freememimage(Memimage *i)
121 {
122         if(i == nil)
123                 return;
124         if(--i->data->ref == 0 && i->data->allocd){
125                 if(i->data->base)
126                         poolfree(imagmem, i->data->base);
127                 free(i->data);
128         }
129         free(i);
130 }
131
132 /*
133  * Wordaddr is deprecated.
134  */
135 ulong*
136 wordaddr(Memimage *i, Point p)
137 {
138         return (ulong*) ((uintptr)byteaddr(i, p) & ~(sizeof(ulong)-1));
139 }
140
141 uchar*
142 byteaddr(Memimage *i, Point p)
143 {
144         uchar *a;
145
146         a = i->data->bdata+i->zero+(int)(sizeof(ulong)*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;
158         }
159         else
160                 return a+p.x*(i->depth/8);
161 }
162
163 int
164 memsetchan(Memimage *i, ulong chan)
165 {
166         int d;
167         int t, j, k;
168         ulong cc;
169         int bytes;
170
171         if((d = chantodepth(chan)) == 0) {
172                 werrstr("bad channel descriptor");
173                 return -1;
174         }
175
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;
185                 }
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;
193                 }
194
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;
200         }
201         i->nchan = k;
202         if(bytes)
203                 i->flags |= Fbytes;
204         return 0;
205 }