1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <memdraw.h>
5 #include <pool.h>
6
7 extern Pool* imagmem;
8
9 void
memdrawallocinit(void)10 memdrawallocinit(void)
11 {
12 if(strcmp(imagmem->name, "Image") == 0 || strcmp(imagmem->name, "image") == 0)
13 imagmem->move = memimagemove;
14 }
15
16 void
memimagemove(void * from,void * to)17 memimagemove(void *from, void *to)
18 {
19 Memdata *md;
20
21 md = *(Memdata**)to;
22 if(md->base != from){
23 print("compacted data not right: #%p\n", md->base);
24 abort();
25 }
26 md->base = to;
27
28 /* if allocmemimage changes this must change too */
29 md->bdata = (uchar*)md->base+sizeof(Memdata*)+sizeof(ulong);
30 }
31
32 Memimage*
allocmemimaged(Rectangle r,ulong chan,Memdata * md)33 allocmemimaged(Rectangle r, ulong chan, Memdata *md)
34 {
35 int d;
36 ulong l;
37 Memimage *i;
38
39 if(Dx(r) <= 0 || Dy(r) <= 0){
40 werrstr("bad rectangle %R", r);
41 return nil;
42 }
43 if((d = chantodepth(chan)) == 0) {
44 werrstr("bad channel descriptor %.8lux", chan);
45 return nil;
46 }
47
48 l = wordsperline(r, d);
49
50 i = mallocz(sizeof(Memimage), 1);
51 if(i == nil)
52 return nil;
53
54 i->data = md;
55 i->zero = sizeof(ulong)*l*r.min.y;
56
57 if(r.min.x >= 0)
58 i->zero += (r.min.x*d)/8;
59 else
60 i->zero -= (-r.min.x*d+7)/8;
61 i->zero = -i->zero;
62 i->width = l;
63 i->r = r;
64 i->clipr = r;
65 i->flags = 0;
66 i->layer = nil;
67 i->cmap = memdefcmap;
68 if(memsetchan(i, chan) < 0){
69 free(i);
70 return nil;
71 }
72 return i;
73 }
74
75 Memimage*
allocmemimage(Rectangle r,ulong chan)76 allocmemimage(Rectangle r, ulong chan)
77 {
78 int d;
79 uchar *p;
80 ulong l, nw;
81 Memdata *md;
82 Memimage *i;
83
84 if((d = chantodepth(chan)) == 0) {
85 werrstr("bad channel descriptor %.8lux", chan);
86 return nil;
87 }
88
89 l = wordsperline(r, d);
90 nw = l*Dy(r);
91 md = malloc(sizeof(Memdata));
92 if(md == nil)
93 return nil;
94
95 md->ref = 1;
96 md->base = poolalloc(imagmem, sizeof(Memdata*)+(1+nw)*sizeof(ulong));
97 if(md->base == nil){
98 free(md);
99 return nil;
100 }
101
102 p = (uchar*)md->base;
103 *(Memdata**)p = md;
104 p += sizeof(Memdata*);
105
106 *(ulong*)p = getcallerpc(&r);
107 p += sizeof(ulong);
108
109 /* if this changes, memimagemove must change too */
110 md->bdata = p;
111 md->allocd = 1;
112
113 i = allocmemimaged(r, chan, md);
114 if(i == nil){
115 poolfree(imagmem, md->base);
116 free(md);
117 return nil;
118 }
119 md->imref = i;
120 return i;
121 }
122
123 void
freememimage(Memimage * i)124 freememimage(Memimage *i)
125 {
126 if(i == nil)
127 return;
128 if(i->data->ref-- == 1 && i->data->allocd){
129 if(i->data->base)
130 poolfree(imagmem, i->data->base);
131 free(i->data);
132 }
133 free(i);
134 }
135