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