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