]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libmemdraw/alloc.c
audio(3): document audiostat/audioctl and speed+delay controls on volume
[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(Dx(r) <= 0 || Dy(r) <= 0){
31                 werrstr("bad rectangle %R", r);
32                 return nil;
33         }
34         if((d = chantodepth(chan)) == 0) {
35                 werrstr("bad channel descriptor %.8lux", chan);
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
80         l = wordsperline(r, d);
81         nw = l*Dy(r);
82         md = malloc(sizeof(Memdata));
83         if(md == nil)
84                 return nil;
85
86         md->ref = 1;
87         md->base = poolalloc(imagmem, sizeof(Memdata*)+(1+nw)*sizeof(ulong));
88         if(md->base == nil){
89                 free(md);
90                 return nil;
91         }
92
93         p = (uchar*)md->base;
94         *(Memdata**)p = md;
95         p += sizeof(Memdata*);
96
97         *(ulong*)p = getcallerpc(&r);
98         p += sizeof(ulong);
99
100         /* if this changes, memimagemove must change too */
101         md->bdata = p;
102         md->allocd = 1;
103
104         i = allocmemimaged(r, chan, md);
105         if(i == nil){
106                 poolfree(imagmem, md->base);
107                 free(md);
108                 return nil;
109         }
110         md->imref = i;
111         return i;
112 }
113
114 void
115 freememimage(Memimage *i)
116 {
117         if(i == nil)
118                 return;
119         if(i->data->ref-- == 1 && i->data->allocd){
120                 if(i->data->base)
121                         poolfree(imagmem, i->data->base);
122                 free(i->data);
123         }
124         free(i);
125 }
126
127 /*
128  * Wordaddr is deprecated.
129  */
130 ulong*
131 wordaddr(Memimage *i, Point p)
132 {
133         return (ulong*) ((uintptr)byteaddr(i, p) & ~(sizeof(ulong)-1));
134 }
135
136 uchar*
137 byteaddr(Memimage *i, Point p)
138 {
139         uchar *a;
140
141         a = i->data->bdata+i->zero+sizeof(ulong)*p.y*i->width;
142
143         if(i->depth < 8){
144                 /*
145                  * We need to always round down,
146                  * but C rounds toward zero.
147                  */
148                 int np;
149                 np = 8/i->depth;
150                 if(p.x < 0)
151                         return a+(p.x-np+1)/np;
152                 else
153                         return a+p.x/np;
154         }
155         else
156                 return a+p.x*(i->depth/8);
157 }
158
159 int
160 memsetchan(Memimage *i, ulong chan)
161 {
162         int d;
163         int t, j, k;
164         ulong cc;
165         int bytes;
166
167         if((d = chantodepth(chan)) == 0) {
168                 werrstr("bad channel descriptor");
169                 return -1;
170         }
171
172         i->depth = d;
173         i->chan = chan;
174         i->flags &= ~(Fgrey|Falpha|Fcmap|Fbytes);
175         bytes = 1;
176         for(cc=chan, j=0, k=0; cc; j+=NBITS(cc), cc>>=8, k++){
177                 t=TYPE(cc);
178                 if(t < 0 || t >= NChan){
179                         werrstr("bad channel string");
180                         return -1;
181                 }
182                 if(t == CGrey)
183                         i->flags |= Fgrey;
184                 if(t == CAlpha)
185                         i->flags |= Falpha;
186                 if(t == CMap && i->cmap == nil){
187                         i->cmap = memdefcmap;
188                         i->flags |= Fcmap;
189                 }
190
191                 i->shift[t] = j;
192                 i->mask[t] = (1<<NBITS(cc))-1;
193                 i->nbits[t] = NBITS(cc);
194                 if(NBITS(cc) != 8)
195                         bytes = 0;
196         }
197         i->nchan = k;
198         if(bytes)
199                 i->flags |= Fbytes;
200         return 0;
201 }