alloc.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <draw.h>
  12. #include <memdraw.h>
  13. #define poolalloc(a, b) malloc(b)
  14. #define poolfree(a, b) free(b)
  15. void
  16. memimagemove(void *from, void *to)
  17. {
  18. Memdata *md;
  19. md = *(Memdata**)to;
  20. if(md->base != from){
  21. print("compacted data not right: #%p\n", md->base);
  22. abort();
  23. }
  24. md->base = to;
  25. /* if allocmemimage changes this must change too */
  26. md->bdata = (uint8_t*)md->base+sizeof(Memdata*)+sizeof(uint32_t);
  27. }
  28. Memimage*
  29. allocmemimaged(Rectangle r, uint32_t chan, Memdata *md, void *X)
  30. {
  31. int d;
  32. uint32_t l;
  33. Memimage *i;
  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. l = wordsperline(r, d);
  43. i = mallocz(sizeof(Memimage), 1);
  44. if(i == nil)
  45. return nil;
  46. i->X = X;
  47. i->data = md;
  48. i->zero = sizeof(uint32_t)*l*r.min.y;
  49. if(r.min.x >= 0)
  50. i->zero += (r.min.x*d)/8;
  51. else
  52. i->zero -= (-r.min.x*d+7)/8;
  53. i->zero = -i->zero;
  54. i->width = l;
  55. i->r = r;
  56. i->clipr = r;
  57. i->flags = 0;
  58. i->layer = nil;
  59. i->cmap = memdefcmap;
  60. if(memsetchan(i, chan) < 0){
  61. free(i);
  62. return nil;
  63. }
  64. return i;
  65. }
  66. Memimage*
  67. _allocmemimage(Rectangle r, uint32_t chan)
  68. {
  69. int d;
  70. uint32_t l, nw;
  71. uint8_t *p;
  72. Memdata *md;
  73. Memimage *i;
  74. if((d = chantodepth(chan)) == 0) {
  75. werrstr("bad channel descriptor %.8lux", chan);
  76. return nil;
  77. }
  78. l = wordsperline(r, d);
  79. nw = l*Dy(r);
  80. md = malloc(sizeof(Memdata));
  81. if(md == nil)
  82. return nil;
  83. md->ref = 1;
  84. md->base = poolalloc(imagmem,
  85. sizeof(Memdata*)+(1+nw)*sizeof(uint32_t));
  86. if(md->base == nil){
  87. free(md);
  88. return nil;
  89. }
  90. p = (uint8_t*)md->base;
  91. *(Memdata**)p = md;
  92. p += sizeof(Memdata*);
  93. *(uint32_t*)p = getcallerpc();
  94. p += sizeof(uint32_t);
  95. /* if this changes, memimagemove must change too */
  96. md->bdata = p;
  97. md->allocd = 1;
  98. i = allocmemimaged(r, chan, md, nil);
  99. if(i == nil){
  100. poolfree(imagmem, md->base);
  101. free(md);
  102. return nil;
  103. }
  104. md->imref = i;
  105. return i;
  106. }
  107. void
  108. _freememimage(Memimage *i)
  109. {
  110. if(i == nil)
  111. return;
  112. if(i->data->ref-- == 1 && i->data->allocd){
  113. if(i->data->base)
  114. poolfree(imagmem, i->data->base);
  115. free(i->data);
  116. }
  117. free(i);
  118. }
  119. /*
  120. * Wordaddr is deprecated.
  121. */
  122. uint32_t*
  123. wordaddr(Memimage *i, Point p)
  124. {
  125. return (uint32_t*) ((uintptr)byteaddr(i, p) & ~(sizeof(uint32_t)-1));
  126. }
  127. uint8_t*
  128. byteaddr(Memimage *i, Point p)
  129. {
  130. uint8_t *a;
  131. a = i->data->bdata+i->zero+sizeof(uint32_t)*p.y*i->width;
  132. if(i->depth < 8){
  133. /*
  134. * We need to always round down,
  135. * but C rounds toward zero.
  136. */
  137. int np;
  138. np = 8/i->depth;
  139. if(p.x < 0)
  140. return a+(p.x-np+1)/np;
  141. else
  142. return a+p.x/np;
  143. }
  144. else
  145. return a+p.x*(i->depth/8);
  146. }
  147. int
  148. memsetchan(Memimage *i, uint32_t chan)
  149. {
  150. int d;
  151. int t, j, k;
  152. uint32_t cc;
  153. int bytes;
  154. if((d = chantodepth(chan)) == 0) {
  155. werrstr("bad channel descriptor");
  156. return -1;
  157. }
  158. i->depth = d;
  159. i->chan = chan;
  160. i->flags &= ~(Fgrey|Falpha|Fcmap|Fbytes);
  161. bytes = 1;
  162. for(cc=chan, j=0, k=0; cc; j+=NBITS(cc), cc>>=8, k++){
  163. t=TYPE(cc);
  164. if(t < 0 || t >= NChan){
  165. werrstr("bad channel string");
  166. return -1;
  167. }
  168. if(t == CGrey)
  169. i->flags |= Fgrey;
  170. if(t == CAlpha)
  171. i->flags |= Falpha;
  172. if(t == CMap && i->cmap == nil){
  173. i->cmap = memdefcmap;
  174. i->flags |= Fcmap;
  175. }
  176. i->shift[t] = j;
  177. i->mask[t] = (1<<NBITS(cc))-1;
  178. i->nbits[t] = NBITS(cc);
  179. if(NBITS(cc) != 8)
  180. bytes = 0;
  181. }
  182. i->nchan = k;
  183. if(bytes)
  184. i->flags |= Fbytes;
  185. return 0;
  186. }